from __future__ import annotations

import argparse
import json
from pathlib import Path

try:
    from cf_cli.registry import register_command
except ImportError:  # pragma: no cover - optional dependency
    register_command = None

from .renderer import build_report_payload, render_report_html


def render_report_artifacts(
    manifest: str,
    *,
    report_uri: str | None = None,
    output: str | None = None,
    data_output: str | None = None,
    data_url: str | None = None,
) -> tuple[Path, Path]:
    manifest_path = Path(manifest).expanduser().resolve()
    output_path = Path(output).expanduser().resolve() if output else manifest_path.with_suffix(".report.html")
    data_output_path = (
        Path(data_output).expanduser().resolve()
        if data_output
        else output_path.with_suffix(".data.json")
    )
    resolved_data_url = data_url or data_output_path.name

    payload = build_report_payload(str(manifest_path), report_uri=report_uri)
    data_output_path.write_text(json.dumps(payload, indent=2), encoding="utf-8")

    html = render_report_html(data_url=resolved_data_url)
    output_path.write_text(html, encoding="utf-8")
    return output_path, data_output_path


def _run_from_args(args: argparse.Namespace) -> int:
    output_path, data_output_path = render_report_artifacts(
        args.manifest,
        report_uri=args.report_uri,
        output=args.output,
        data_output=args.data_output,
        data_url=args.data_url,
    )
    print(f"Wrote report to {output_path}")
    print(f"Wrote report data to {data_output_path}")
    return 0


def _configure_parser(parser: argparse.ArgumentParser) -> None:
    parser.add_argument("manifest", help="Path to a pipeline manifest (RDF: Turtle, structured JSON, or N-Quads).")
    parser.add_argument("--report-uri", help="Optional report IRI. If omitted, must be exactly one cf:Report in manifest.")
    parser.add_argument("--output", help="Output HTML file path. Defaults to <manifest>.report.html")
    parser.add_argument(
        "--data-output",
        help="Output JSON data path for the Observable runtime (defaults to <output>.data.json).",
    )
    parser.add_argument(
        "--data-url",
        help="URL or relative path the HTML should fetch for data (defaults to the data output file name).",
    )
    parser.set_defaults(func=_run_from_args, _cf_handler=_run_from_args)


def _build_parser(*, prog: str = "cf pipeline report-render") -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        prog=prog,
        description="Render a Cogniflow pipeline report to HTML.",
    )
    _configure_parser(parser)
    return parser


def run(
    argv: list[str] | None = None,
    *,
    prog: str = "cf pipeline report-render",
) -> int:
    parser = _build_parser(prog=prog)
    args = parser.parse_args(argv)
    handler = getattr(args, "func", None)
    if handler is None:
        parser.print_help()
        return 1
    return int(handler(args) or 0)


def main() -> int:
    return run()


def _add_cf_parser(subparsers: argparse._SubParsersAction) -> argparse.ArgumentParser:
    parser = subparsers.add_parser("report-render", help="Render a pipeline report to HTML.")
    _configure_parser(parser)
    return parser


def _register_cf_cli() -> None:
    if register_command is None:
        return
    register_command(
        "pipeline",
        "report-render",
        _add_cf_parser,
        group_help="Pipeline tools",
        command_help="Render a pipeline report to HTML",
    )


if __name__ == "__main__":
    raise SystemExit(main())

_register_cf_cli()
