import argparse
import json
import sys
import zipfile

from .parser import (
    parse_report_layout,
    parse_data_model,
    parse_mashup,
    parse_connections,
    infer_model_from_references,
    build_lineage,
)
from .planner import generate_plan


def _load_analysis(pbix_path: str):
    with zipfile.ZipFile(pbix_path) as z:
        layout = parse_report_layout(z)
        model = parse_data_model(z)
        mashup = parse_mashup(z)
        connections = parse_connections(z)

    if not model or model.get("is_missing"):
        model = infer_model_from_references(layout.get("all_visuals_flat", []))

    lineage = build_lineage(
        layout.get("all_visuals_flat", []),
        model,
        mashup.get("queries", []) if mashup else [],
    )

    return {
        "filename": pbix_path,
        "parsed_layout": layout,
        "parsed_model": model,
        "parsed_mashup": mashup,
        "connections": connections,
        "lineage": lineage,
    }


def _write_output(data, output_path: str | None, pretty: bool):
    if pretty:
        payload = json.dumps(data, indent=2)
    else:
        payload = json.dumps(data)

    if output_path:
        with open(output_path, "w", encoding="utf-8") as f:
            f.write(payload)
    else:
        sys.stdout.write(payload)
        sys.stdout.write("\n")


def main(argv: list[str] | None = None) -> int:
    parser = argparse.ArgumentParser(
        prog="riff-pbix",
        description="Parse a PBIX file and generate a Riff app plan.",
    )
    parser.add_argument("pbix", help="Path to the .pbix file")
    parser.add_argument("--output", "-o", help="Write JSON output to a file")
    parser.add_argument(
        "--analysis",
        action="store_true",
        help="Output the full analysis result instead of the app plan",
    )
    parser.add_argument(
        "--pretty",
        action="store_true",
        help="Pretty-print JSON output",
    )

    args = parser.parse_args(argv)

    analysis = _load_analysis(args.pbix)

    if args.analysis:
        _write_output(analysis, args.output, args.pretty)
    else:
        plan = generate_plan(analysis)
        if hasattr(plan, "model_dump"):
            payload = plan.model_dump()
        else:
            payload = plan.dict()
        _write_output(payload, args.output, args.pretty)

    return 0


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