from __future__ import annotations

import argparse
import sys

from supersonar.config import Config, load_config
from supersonar.models import Severity
from supersonar.quality_gate import evaluate_gate
from supersonar.reporters import to_json_report, to_sarif_report, write_report
from supersonar.scanner import scan_path


def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(prog="supersonar", description="Static analysis scanner for Python.")
    subparsers = parser.add_subparsers(dest="command", required=True)

    scan = subparsers.add_parser("scan", help="Run static analysis scan.")
    scan.add_argument("path", nargs="?", default=".", help="Path to scan.")
    scan.add_argument("--config", help="Path to supersonar TOML config.")
    scan.add_argument("--exclude", action="append", default=[], help="Extra exclude directory names.")
    scan.add_argument("--format", choices=["json", "sarif"], help="Report output format.")
    scan.add_argument("--out", help="Write report to file. Defaults to stdout.")
    scan.add_argument("--fail-on", choices=["low", "medium", "high", "critical"], help="Fail on severity level.")
    scan.add_argument("--max-issues", type=int, help="Fail if issue count exceeds this number.")

    return parser


def main() -> None:
    parser = build_parser()
    args = parser.parse_args()

    if args.command == "scan":
        exit_code = run_scan(args)
        raise SystemExit(exit_code)


def run_scan(args: argparse.Namespace) -> int:
    config = load_config(args.config)
    merged = merge_cli_with_config(args, config)

    result = scan_path(args.path, excludes=merged.scan.exclude)
    report_payload = render_report(result, merged.report.output_format)
    write_report(report_payload, merged.report.out)

    passed, reasons = evaluate_gate(
        result,
        fail_on=merged.quality_gate.fail_on,
        max_issues=merged.quality_gate.max_issues,
    )
    if not passed:
        for reason in reasons:
            print(f"[gate] {reason}", file=sys.stderr)
        return 2
    return 0


def merge_cli_with_config(args: argparse.Namespace, config: Config) -> Config:
    merged = config
    if args.exclude:
        merged.scan.exclude = list(dict.fromkeys([*merged.scan.exclude, *args.exclude]))
    if args.format:
        merged.report.output_format = args.format
    if args.out:
        merged.report.out = args.out
    if args.fail_on:
        merged.quality_gate.fail_on = args.fail_on
    if args.max_issues is not None:
        merged.quality_gate.max_issues = args.max_issues
    return merged


def render_report(result, output_format: str):
    if output_format == "sarif":
        return to_sarif_report(result)
    if output_format == "json":
        return to_json_report(result)
    raise ValueError(f"Unsupported report format: {output_format}")


if __name__ == "__main__":
    main()

