#!/usr/bin/env python3
from __future__ import annotations

import argparse
import json
import shutil
import sys
from pathlib import Path
from typing import Any

ROOT = Path(__file__).resolve().parents[1]
BACKEND = ROOT / "backend"
if str(BACKEND) not in sys.path:
    sys.path.insert(0, str(BACKEND))

from app.services.analytics_youtube_csv import (  # noqa: E402
    UNKNOWN,
    YOUTUBE_CHART,
    YOUTUBE_DAILY_TOTALS,
    YOUTUBE_VIDEO_TABLE,
    file_hash,
    parse_csv_by_type,
)

TYPE_TO_LABEL = {
    YOUTUBE_DAILY_TOTALS: "Gesamtwerte",
    YOUTUBE_VIDEO_TABLE: "Tabellendaten",
    YOUTUBE_CHART: "Diagrammdaten",
}
LABEL_TO_TARGET = {
    "Diagrammdaten": "{date_prefix}_Diagrammdaten.csv",
    "Gesamtwerte": "{date_prefix}_Gesamtwerte.csv",
    "Tabellendaten": "{date_prefix}_Tabellendaten.csv",
}


def analyze_file(path: Path) -> dict[str, Any]:
    content = path.read_bytes()
    parsed = parse_csv_by_type(content)
    label = TYPE_TO_LABEL.get(parsed.detected_type, "Unknown")
    return {
        "source": path.name,
        "source_path": str(path),
        "detected_type": parsed.detected_type,
        "label": label,
        "rows": parsed.row_count,
        "data_rows": len(parsed.rows),
        "size": path.stat().st_size,
        "sha256": file_hash(content),
        "warnings": list(parsed.warnings),
        "errors": list(parsed.errors),
    }


def candidate_sort_key(item: dict[str, Any], date_prefix: str) -> tuple[int, int, int]:
    expected = LABEL_TO_TARGET.get(item["label"], "").format(date_prefix=date_prefix)
    canonical_bonus = 1 if item["source"] == expected else 0
    return (canonical_bonus, int(item.get("data_rows") or 0), int(item.get("size") or 0))


def canonicalize(source_dir: Path, target_dir: Path, date_prefix: str) -> dict[str, Any]:
    source_dir = source_dir.expanduser().resolve()
    target_dir = target_dir.expanduser().resolve()
    if not source_dir.exists():
        raise SystemExit(f"source_dir does not exist: {source_dir}")
    target_dir.mkdir(parents=True, exist_ok=True)

    analyzed = [analyze_file(path) for path in sorted(source_dir.glob("*.csv"))]
    warnings: list[str] = []
    by_label: dict[str, list[dict[str, Any]]] = {}
    for item in analyzed:
        if item["label"] == "Unknown":
            warnings.append(f"{item['source']}: unknown CSV header; skipped")
            continue
        by_label.setdefault(item["label"], []).append(item)

    recognized: dict[str, dict[str, Any]] = {}
    for label, items in sorted(by_label.items()):
        items = sorted(items, key=lambda item: candidate_sort_key(item, date_prefix), reverse=True)
        chosen = items[0]
        target_name = LABEL_TO_TARGET[label].format(date_prefix=date_prefix)
        target_path = target_dir / target_name
        source_path = Path(chosen["source_path"])
        if source_path.resolve() != target_path.resolve():
            shutil.copy2(source_path, target_path)
        copied_content = target_path.read_bytes()
        recognized[label] = {
            "source": chosen["source"],
            "target": target_name,
            "rows": chosen["rows"],
            "data_rows": chosen["data_rows"],
            "size": target_path.stat().st_size,
            "sha256": file_hash(copied_content),
            "detected_type": chosen["detected_type"],
            "warnings": chosen["warnings"],
        }
        for duplicate in items[1:]:
            warnings.append(
                f"{duplicate['source']}: also detected as {label}; kept as raw file, canonical target uses {chosen['source']}"
            )

    missing = [label for label in ["Diagrammdaten", "Gesamtwerte", "Tabellendaten"] if label not in recognized]
    report = {
        "source_dir": str(source_dir),
        "target_dir": str(target_dir),
        "recognized": recognized,
        "missing": missing,
        "warnings": warnings,
        "files": analyzed,
    }
    manifest = target_dir / f"{date_prefix}_youtube_csv_canonicalization_manifest.json"
    manifest.write_text(json.dumps(report, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
    report["manifest"] = str(manifest)
    return report


def main() -> None:
    parser = argparse.ArgumentParser(description="Canonicalize YouTube Analytics CSVs by header/content detection.")
    parser.add_argument("--source-dir", required=True)
    parser.add_argument("--target-dir", required=True)
    parser.add_argument("--date-prefix", required=True)
    args = parser.parse_args()
    report = canonicalize(Path(args.source_dir), Path(args.target_dir), args.date_prefix)
    print(json.dumps(report, indent=2, ensure_ascii=False))


if __name__ == "__main__":
    main()
