"""whoson -- lightweight subnet audit tool."""

import argparse
import sys
import time

from discovery.nmap_scan import NetworkScanner
from graph.topology_builder import TopologyBuilder
from utils.exporters import TopologyExporter


def _print_table(scan_results):
    """Print a host table to stdout."""
    hosts = scan_results.get('hosts', [])
    if not hosts:
        print("No hosts found.")
        return

    builder = TopologyBuilder()

    rows = []
    for h in hosts:
        host_type = builder._classify_host(h)
        ports = ','.join(str(p['port']) for p in h.get('open_ports', []))
        rows.append({
            'ip': h.get('ip', ''),
            'hostname': h.get('hostname', '') or '-',
            'type': host_type,
            'mac': h.get('mac_address', '') or '-',
            'vendor': h.get('vendor', '') or '-',
            'ports': ports or '-',
        })

    col_widths = {
        'ip': max(len('IP'), max(len(r['ip']) for r in rows)),
        'hostname': max(len('Hostname'), max(len(r['hostname']) for r in rows)),
        'type': max(len('Type'), max(len(r['type']) for r in rows)),
        'mac': max(len('MAC'), max(len(r['mac']) for r in rows)),
        'vendor': max(len('Vendor'), max(len(r['vendor']) for r in rows)),
        'ports': max(len('Ports'), max(len(r['ports']) for r in rows)),
    }

    header = (
        f"{'IP':<{col_widths['ip']}}  "
        f"{'Hostname':<{col_widths['hostname']}}  "
        f"{'Type':<{col_widths['type']}}  "
        f"{'MAC':<{col_widths['mac']}}  "
        f"{'Vendor':<{col_widths['vendor']}}  "
        f"{'Ports':<{col_widths['ports']}}"
    )
    sep = '-' * len(header)

    print(header)
    print(sep)
    for r in rows:
        print(
            f"{r['ip']:<{col_widths['ip']}}  "
            f"{r['hostname']:<{col_widths['hostname']}}  "
            f"{r['type']:<{col_widths['type']}}  "
            f"{r['mac']:<{col_widths['mac']}}  "
            f"{r['vendor']:<{col_widths['vendor']}}  "
            f"{r['ports']:<{col_widths['ports']}}"
        )


def main(argv=None):
    parser = argparse.ArgumentParser(
        prog='whoson',
        description='Lightweight subnet audit tool -- see what is alive on your network.',
    )
    parser.add_argument(
        'subnet',
        help='Network in CIDR notation (e.g. 192.168.1.0/24)',
    )
    parser.add_argument(
        '-t', '--type',
        choices=['ping', 'tcp', 'syn'],
        default='tcp',
        help='Scan type (default: tcp)',
    )
    parser.add_argument(
        '-i', '--image',
        metavar='FILE',
        help='Save topology image (format from extension: .png, .jpg, .svg)',
    )
    parser.add_argument(
        '--json',
        metavar='FILE',
        dest='json_file',
        help='Save topology data as JSON',
    )
    parser.add_argument(
        '--csv',
        metavar='FILE',
        dest='csv_file',
        help='Save host list as CSV',
    )
    parser.add_argument(
        '-q', '--quiet',
        action='store_true',
        help='Suppress table output (only write files)',
    )

    args = parser.parse_args(argv)

    scanner = NetworkScanner()

    if not scanner.validate_subnet(args.subnet):
        print(f"Error: invalid subnet '{args.subnet}'", file=sys.stderr)
        sys.exit(1)

    info = scanner.get_network_info(args.subnet)
    if not args.quiet:
        print(f"Scanning {args.subnet}  ({info['usable_addresses']} usable addresses, {args.type} scan)")

    t0 = time.time()
    scan_results = scanner.scan_subnet(args.subnet, args.type)
    elapsed = time.time() - t0

    total = scan_results['total_hosts']
    if not args.quiet:
        print(f"Found {total} host{'s' if total != 1 else ''} in {elapsed:.1f}s\n")

    if total == 0:
        return

    if not args.quiet:
        _print_table(scan_results)

    builder = TopologyBuilder()
    topology_data = builder.build_topology(scan_results)
    exporter = TopologyExporter()

    if args.image:
        exporter.export_image(topology_data, args.image)
        if not args.quiet:
            print(f"\nImage saved to {args.image}")

    if args.json_file:
        json_str = exporter.export_json(topology_data)
        with open(args.json_file, 'w', encoding='utf-8') as f:
            f.write(json_str)
        if not args.quiet:
            print(f"JSON saved to {args.json_file}")

    if args.csv_file:
        csv_str = exporter.export_csv_nodes(topology_data)
        with open(args.csv_file, 'w', encoding='utf-8') as f:
            f.write(csv_str)
        if not args.quiet:
            print(f"CSV saved to {args.csv_file}")


if __name__ == '__main__':
    main()
