"""Seed the function_library table from YAML files in seeds/function_library/.

All writes go through :func:`EdgeFunctionsService.upsert_library_function_from_manifest`.

Usage:
    python scripts/seed_function_library.py
    python scripts/seed_function_library.py --dry-run
    python scripts/seed_function_library.py --slug stripe-create-checkout
    python scripts/seed_function_library.py --mode safe|force|metadata-only|create-version
"""
from __future__ import annotations

import argparse
import asyncio
import sys
from pathlib import Path

import yaml

# Add project root to sys.path so src imports work
REPO_ROOT = Path(__file__).parent.parent
sys.path.insert(0, str(REPO_ROOT))

SEEDS_DIR = REPO_ROOT / "seeds" / "function_library"


async def _run(
    slug_filter: str | None,
    dry_run: bool,
    mode: str,
) -> None:
    from src.core.database import async_session_factory
    from src.domain.edge_functions.repository import (
        FunctionLibraryRepository,
        FunctionLibraryVersionRepository,
        ProjectFunctionRepository,
        ProjectFunctionTokenRepository,
        ProjectFunctionVersionRepository,
        ProjectWebhookEndpointRepository,
        WorkerRuntimeVersionRepository,
    )
    from src.domain.connectors.repository import ConnectorRepository
    from src.domain.edge_functions.service import EdgeFunctionsService
    from src.domain.functions.library_manifest_schema import (
        parse_manifest,
        resolve_code_template_path,
    )
    from src.domain.projects.repository import ProjectRepository
    from src.integrations.cloud_control_client import CloudControlClient

    files = sorted(SEEDS_DIR.glob("*.yaml"))
    if not files:
        print(f"No YAML files found in {SEEDS_DIR}")
        return

    if slug_filter:
        files = [f for f in files if f.stem == slug_filter]
        if not files:
            print(f"No seed file found for slug: {slug_filter}")
            sys.exit(1)

    force = mode == "force"
    metadata_only = mode == "metadata-only"
    create_version = mode == "create-version"

    async with async_session_factory() as db:
        svc = EdgeFunctionsService(
            library_repo=FunctionLibraryRepository(db),
            library_version_repo=FunctionLibraryVersionRepository(db),
            fn_repo=ProjectFunctionRepository(db),
            version_repo=ProjectFunctionVersionRepository(db),
            webhook_repo=ProjectWebhookEndpointRepository(db),
            runtime_repo=WorkerRuntimeVersionRepository(db),
            token_repo=ProjectFunctionTokenRepository(db),
            project_repo=ProjectRepository(db),
            connector_repo=ConnectorRepository(db),
            cloud_client=CloudControlClient(),
        )

        for path in files:
            raw = yaml.safe_load(path.read_text(encoding="utf-8")) or {}
            rel_seed_path = f"seeds/function_library/{path.name}"
            slug = raw.get("slug") or path.stem
            raw.setdefault("slug", slug)
            try:
                manifest = parse_manifest(raw, overrides={"seed_path": rel_seed_path})
            except Exception as e:
                print(f"[error] {path.name}: {e}")
                continue

            manifest = resolve_code_template_path(manifest, REPO_ROOT)

            result = await svc.upsert_library_function_from_manifest(
                manifest=manifest,
                source="seed",
                seed_path=rel_seed_path,
                dry_run=dry_run,
                force=force,
                metadata_only=metadata_only,
                create_version=create_version,
            )

            if result.skipped:
                print(f"Skip {slug}: {result.skip_reason}")
            elif dry_run:
                print(f"[dry-run] would upsert {slug} created={result.created} hash={result.manifest_hash!r}")
            else:
                print(
                    f"OK {slug}: created={result.created} "
                    f"meta+={result.metadata_changed} ver+={result.versioned_changed}"
                )

        if not dry_run:
            await db.commit()
            print(f"\nSeeded {len(files)} function(s).")
        else:
            print(f"\n[dry-run] Would process {len(files)} function(s).")


def main() -> None:
    parser = argparse.ArgumentParser(
        description="Seed function_library from YAML via manifest service"
    )
    parser.add_argument("--dry-run", action="store_true", help="Preview without writing")
    parser.add_argument("--slug", help="Only process this slug / seed file")
    parser.add_argument(
        "--mode",
        choices=["safe", "force", "metadata-only", "create-version"],
        default="safe",
        help="safe: default; force: overwrite admin_override seeds; "
        "metadata-only: mutable fields only; create-version: also snapshot a version",
    )
    args = parser.parse_args()

    asyncio.run(_run(slug_filter=args.slug, dry_run=args.dry_run, mode=args.mode))


if __name__ == "__main__":
    main()
