"""Command-line interface for RTSP Scanner"""

import argparse
import sys
from pathlib import Path

from rtsp_scanner.core.port_scanner import PortScanner
from rtsp_scanner.core.rtsp_tester import RTSPTester
from rtsp_scanner.core.channel_scanner import ChannelScanner
from rtsp_scanner.utils.logger import setup_logger
from rtsp_scanner.utils.output import OutputFormatter
from rtsp_scanner.utils.network import get_local_network, get_local_ip


def main():
    """Main CLI entry point"""
    parser = argparse.ArgumentParser(
        description='Network RTSP stream scanner and debugger',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  # Scan local network (auto-detected)
  rtsp-network-scanner scan

  # Scan specific network
  rtsp-network-scanner scan 192.168.1.0/24

  # Scan single host
  rtsp-network-scanner scan 192.168.1.100
        """
    )

    parser.add_argument('--debug', action='store_true', help='Enable debug logging')
    parser.add_argument('--log-file', type=str, help='Log to file')
    parser.add_argument('--output', '-o', type=str, help='Output file (JSON or CSV)')
    parser.add_argument('--timeout', type=float, default=2.0, help='Connection timeout (default: 2.0s)')
    parser.add_argument('--workers', type=int, default=50, help='Max concurrent workers (default: 50)')

    subparsers = parser.add_subparsers(dest='command', help='Commands')

    # Main scan command - does everything
    scan = subparsers.add_parser('scan', help='Scan for RTSP cameras (ports + channels)')
    scan.add_argument('target', nargs='?', help='Network (CIDR), IP range, or single host (auto-detected if omitted)')
    scan.add_argument('--ports', nargs='+', type=int, help='Ports to scan')
    scan.add_argument('--username', '-u', help='Username for channel scan')
    scan.add_argument('--password', '-p', help='Password for channel scan')
    scan.add_argument('--skip-channels', action='store_true', help='Skip channel discovery')
    scan.add_argument('--verify-playback', action='store_true', help='Verify streams are actually playable')

    # Login command - validate credentials
    login = subparsers.add_parser('login', help='Validate camera credentials')
    login.add_argument('url', help='RTSP URL to test (e.g., rtsp://192.168.1.100:554/stream1)')
    login.add_argument('--username', '-u', required=True, help='Username')
    login.add_argument('--password', '-p', required=True, help='Password')

    # Verify command - check if stream is playable
    verify = subparsers.add_parser('verify', help='Verify stream playback')
    verify.add_argument('url', help='RTSP URL to verify')
    verify.add_argument('--username', '-u', help='Username (if required)')
    verify.add_argument('--password', '-p', help='Password (if required)')

    args = parser.parse_args()

    if not args.command:
        parser.print_help()
        return 1

    # Setup logger
    logger = setup_logger(debug=args.debug, log_file=args.log_file)
    formatter = OutputFormatter()

    try:
        results = []

        # Execute command
        if args.command == 'scan':
            # Determine target
            target = args.target
            if target is None:
                # Auto-detect network
                target = get_local_network()
                local_ip = get_local_ip()
                print(f"Auto-detected network: {target} (Your IP: {local_ip})")

            # Step 1: Scan for open RTSP ports
            print(f"Scanning for RTSP ports on {target}...\n")
            port_scanner = PortScanner(timeout=args.timeout, max_workers=args.workers, logger=logger)

            # Determine if it's a network, range, or single host
            show_progress = not args.debug
            if '/' in target:
                # CIDR network
                port_results = port_scanner.scan_network(target, ports=args.ports, show_progress=show_progress)
            elif '-' in target:
                # IP range (e.g., 192.168.1.1-192.168.1.254)
                parts = target.split('-')
                port_results = port_scanner.scan_ip_range(parts[0].strip(), parts[1].strip(), ports=args.ports, show_progress=show_progress)
            else:
                # Single host
                port_results = port_scanner.scan_host(target, ports=args.ports, show_progress=show_progress)

            # Display port scan results
            if port_results:
                open_results = [r for r in port_results if r.get('status') == 'open']
                if open_results:
                    print(formatter.format_summary(open_results, "Ports"))
                    print(formatter.format_table(open_results, ['host', 'port', 'response_time']))

            # Step 2: Scan for channels on hosts with open ports
            if not args.skip_channels and port_results:
                open_hosts = {}
                for result in port_results:
                    if result.get('status') == 'open':
                        host = result['host']
                        port = result['port']
                        if host not in open_hosts:
                            open_hosts[host] = []
                        open_hosts[host].append(port)

                if open_hosts:
                    total_ports = sum(len(ports) for ports in open_hosts.values())
                    print(f"\nFound {len(open_hosts)} host(s) with {total_ports} open RTSP port(s). Scanning for channels...\n")
                    channel_scanner = ChannelScanner(timeout=args.timeout, max_workers=args.workers, logger=logger)

                    all_channels = []
                    for host, ports in open_hosts.items():
                        for port in ports:
                            channels = channel_scanner.scan_channels(
                                host,
                                port,
                                args.username,
                                args.password,
                                show_progress=not args.debug
                            )

                            # Add host and port info to results
                            for channel in channels:
                                channel['host'] = host
                                channel['port'] = port
                                all_channels.append(channel)

                    # Display channel results
                    if all_channels:
                        print(formatter.format_summary(all_channels, 'Channels'))
                        # Only show codec/resolution if at least one channel has codec data
                        has_codec = any(c.get('codec') for c in all_channels)
                        if has_codec:
                            print(formatter.format_table(all_channels, ['host', 'port', 'path', 'stream_type', 'codec', 'resolution', 'response_time']))
                        else:
                            print(formatter.format_table(all_channels, ['host', 'port', 'path', 'stream_type', 'response_time']))
                        results = all_channels
                    else:
                        print("\nNo accessible channels found")
                        results = port_results
                else:
                    print("\nNo open RTSP ports found")
                    results = port_results
            else:
                results = port_results

        # Handle login command - validate credentials
        elif args.command == 'login':
            tester = RTSPTester(timeout=args.timeout, logger=logger)

            print(f"\nValidating credentials for {args.url}...")
            print(f"Username: {args.username}")
            print(f"Password: {'*' * len(args.password)}\n")

            validation = tester.validate_credentials(args.url, args.username, args.password)

            if validation['valid']:
                print("✓ Credentials are VALID")
                print(f"  Status: 200 OK")
                print(f"  Response time: {formatter._format_response_time(validation['response_time'])}")
                if validation.get('codec'):
                    print(f"  Codec: {validation['codec']}")
                if validation.get('resolution'):
                    print(f"  Resolution: {validation['resolution']}")
            else:
                print("✗ Credentials are INVALID")
                print(f"  Status: {validation.get('status_code', 'N/A')}")
                print(f"  Error: {validation.get('error', 'Unknown error')}")
                return 1

            results = [validation]

        # Handle verify command - check stream playback
        elif args.command == 'verify':
            tester = RTSPTester(timeout=args.timeout, logger=logger)

            print(f"\nVerifying stream playback for {args.url}...\n")

            playback = tester.verify_stream_playback(args.url, args.username, args.password)

            print("Stream Verification Results:")
            print(f"  URL: {args.url}")
            print(f"  Playable: {'✓ YES' if playback['playable'] else '✗ NO'}")
            print(f"  SETUP OK: {'✓' if playback['setup_ok'] else '✗'}")
            print(f"  PLAY OK: {'✓' if playback['play_ok'] else '✗'}")
            print(f"  Data Received: {'✓' if playback['data_received'] else '✗'}")

            if playback.get('error'):
                print(f"  Error: {playback['error']}")
                return 1

            results = [playback]

        # Export results
        if args.output and results:
            output_path = Path(args.output)
            if output_path.suffix.lower() == '.json':
                formatter.export_json(results, args.output)
                print(f"\nExported to {args.output}")
            elif output_path.suffix.lower() == '.csv':
                formatter.export_csv(results, args.output)
                print(f"\nExported to {args.output}")

        return 0

    except KeyboardInterrupt:
        print("\n\nInterrupted")
        return 130
    except Exception as e:
        print(f"\nError: {str(e)}")
        if args.debug:
            raise
        return 1


if __name__ == '__main__':
    sys.exit(main())
