"""
Entry point for cov_change.
"""

import json
import os
from dataclasses import dataclass
from cov_change.utils import bcolors, print_error
from cov_change.coverage_parser import CoverageParser, CoverageSummary
from cov_change.diff_parser import DiffParser
from cov_change.output_writer import print_output

import argparse
from dacite import from_dict
import subprocess


@dataclass
class Args:
    diff_branch: str
    curr_branch: str
    coverage_file: str
    output: str
    verbose: bool
    diff_file: str
    use_coverage_change: bool
    format: str


def _cov_change(args: Args) -> None:
    cov_summary: CoverageSummary | None = None

    if args.use_coverage_change:
        if os.path.exists(args.output):
            with open(args.output, "r") as f:
                json_data = json.load(f)
                try:
                    cov_summary = from_dict(CoverageSummary, json_data)
                except Exception as e:
                    print_error(f"Error parsing {args.output}")
                    print_error(str(e))
                    exit(1)
        else:
            print_error(f"{args.output} not found")
            exit(1)
    else:
        if args.diff_file is None:
            output = subprocess.run(
                ["git", "diff", "--unified=0", args.diff_branch, args.curr_branch],
                capture_output=True,
            )

            if output.returncode != 0:
                print_error(f"Error running git diff")
                print(output.stderr.decode("utf-8"))
                raise Exception("")
            data = output.stdout.decode("utf-8")

        else:
            if not os.path.exists(args.diff_file):
                raise Exception(f"{args.diff_file} not found")
            with open(args.diff_file, "r") as f:
                data = f.read()
        diff_parser = DiffParser(data)
        diff_parser.parse()
        coverage_parser = CoverageParser(args.coverage_file, diff_parser)
        coverage_parser.parse()
        cov_summary = coverage_parser.summary
        with open(args.output, "w") as f:
            f.write(coverage_parser.jsonify())

    print_output(cov_summary, args.verbose, args.format)


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "diff_branch",
        nargs="?",
        help="diff branch/commit to compare against (default: origin/main)",
        default="origin/main",
    )
    parser.add_argument(
        "curr_branch",
        nargs="?",
        help="current branch/commit to compare (default: HEAD)",
        default="HEAD",
    )
    parser.add_argument(
        "--coverage_file",
        help="coverage file generated by running 'coverage json'",
        default="coverage.json",
        required=False,
    )
    parser.add_argument(
        "-o",
        "--output",
        help="json output file",
        default="coverage_change.json",
        required=False,
    )
    parser.add_argument(
        "-v",
        "--verbose",
        help="print extra information",
        default=False,
        required=False,
        action="store_true",
    )

    parser.add_argument(
        "-f",
        "--format",
        help="output format (default: cli)",
        choices=["cli", "markdown"],
        default="cli",
    )

    parser.add_argument(
        "--diff_file",
        help="diff file already generated by running 'git diff --unified=0 <diff_branch> <curr_branch>'",
        default=None,
        required=False,
    )
    parser.add_argument(
        "--use_coverage_change",
        help="use coverage change file generated by previous run",
        default=False,
        action="store_true",
    )

    args: Args = Args(**vars(parser.parse_args()))
    _cov_change(args)


if __name__ == "__main__":
    main()
