#!/usr/bin/env python3
"""
Seed the database with data/seed YAMLs, then load aviation example contracts
from data/aviation_examples into the metadata store.

Run from project root (parent of bin/) or with PYCHARTER_DATABASE_URL set.
Requires: pycharter db init (or existing DB) before first run.

Usage:
  python bin/seed
  python bin/seed --database-url sqlite:///pycharter.db
  python bin/seed --skip-aviation   # only seed data/seed
"""

import argparse
import os
import sys
from pathlib import Path
from typing import Optional


def _project_root() -> Path:
    """Project root = directory containing bin/ (pycharter root)."""
    script = Path(__file__).resolve()
    return script.parent.parent


def _get_db_url(database_url: Optional[str]) -> str:
    url = (
        database_url
        or os.getenv("PYCHARTER_DATABASE_URL")
        or _default_sqlite_url()
    )
    if not url:
        return f"sqlite:///{_project_root() / 'pycharter.db'}"
    return url


def _default_sqlite_url() -> Optional[str]:
    try:
        from pycharter.config import get_database_url
        return get_database_url()
    except Exception:
        return None


def _run_seed(seed_dir: Path, database_url: str) -> int:
    """Run pycharter db seed for the given directory."""
    from pycharter.db.cli import cmd_seed
    return cmd_seed(str(seed_dir), database_url)


def _get_metadata_store(database_url: str):
    """Return a connected metadata store for the given database URL."""
    if database_url.startswith(("postgresql://", "postgres://")):
        from pycharter.metadata_store import PostgresMetadataStore
        store = PostgresMetadataStore(connection_string=database_url)
    else:
        from pycharter.metadata_store import SQLiteMetadataStore
        store = SQLiteMetadataStore(connection_string=database_url)
    store.connect()
    return store


def _seed_aviation_examples(aviation_root: Path, database_url: str) -> int:
    """Load each *_contract.yaml under aviation_root and store in metadata store."""
    from pycharter.contract_parser import parse_contract_file

    contract_files = sorted(aviation_root.rglob("*_contract.yaml"))
    if not contract_files:
        print("No *_contract.yaml files found under data/aviation_examples.")
        return 0

    store = _get_metadata_store(database_url)
    stored = 0
    skipped = 0

    for path in contract_files:
        try:
            parsed = parse_contract_file(str(path), validate=True)
        except Exception as e:
            print(f"  Skip {path.name}: parse error — {e}")
            skipped += 1
            continue

        schema = parsed.schema or {}
        # Store expects schema title to be lowercase alphanumeric + underscores
        schema_name = path.stem.replace("_contract", "").replace("-", "_").lower()
        schema_to_store = dict(schema)
        schema_to_store["title"] = schema_name
        version = (parsed.versions or {}).get("schema") or "1.0.0"
        if isinstance(version, (int, float)):
            version = str(version)

        try:
            schema_id = store.store_schema(schema_name, schema_to_store, version)
        except ValueError as e:
            if "already exists" in str(e).lower():
                print(f"  Skip {path.name}: contract already stored.")
                skipped += 1
                continue
            raise

        # Coercion rules (optional)
        if parsed.coercion_rules:
            cr_version = (parsed.versions or {}).get("coercion_rules") or version
            if isinstance(cr_version, (int, float)):
                cr_version = str(cr_version)
            try:
                store.store_coercion_rules(schema_id, parsed.coercion_rules, version=cr_version)
            except ValueError as e:
                if "already exists" not in str(e).lower():
                    raise

        # Validation rules (optional)
        if parsed.validation_rules:
            vr_version = (parsed.versions or {}).get("validation_rules") or version
            if isinstance(vr_version, (int, float)):
                vr_version = str(vr_version)
            try:
                store.store_validation_rules(schema_id, parsed.validation_rules, version=vr_version)
            except ValueError as e:
                if "already exists" not in str(e).lower():
                    raise

        # Metadata (optional)
        if parsed.metadata:
            meta_version = (parsed.versions or {}).get("metadata") or version
            if isinstance(meta_version, (int, float)):
                meta_version = str(meta_version)
            try:
                store.store_metadata(schema_id, parsed.metadata, version=meta_version)
            except ValueError as e:
                if "already exists" not in str(e).lower():
                    raise

        print(f"  Stored: {schema_name} ({path.relative_to(aviation_root)})")
        stored += 1

    print(f"\nAviation examples: {stored} stored, {skipped} skipped.")
    return 0


def main() -> int:
    parser = argparse.ArgumentParser(
        description="Seed DB with data/seed then data/aviation_examples contracts.",
    )
    parser.add_argument(
        "--database-url",
        default=None,
        help="Database URL (default: PYCHARTER_DATABASE_URL or sqlite:///pycharter.db)",
    )
    parser.add_argument(
        "--skip-aviation",
        action="store_true",
        help="Only run data/seed; do not load aviation_examples.",
    )
    args = parser.parse_args()

    root = _project_root()
    seed_dir = root / "data" / "seed"
    aviation_dir = root / "data" / "aviation_examples"

    if not seed_dir.exists():
        print(f"Seed directory not found: {seed_dir}")
        return 1

    db_url = _get_db_url(args.database_url)
    print(f"Database: {db_url}")
    print(f"Seeding from: {seed_dir}")

    code = _run_seed(seed_dir, db_url)
    if code != 0:
        return code

    if args.skip_aviation:
        return 0

    if not aviation_dir.exists():
        print(f"Aviation examples directory not found: {aviation_dir}")
        return 0

    print(f"\nLoading aviation example contracts from: {aviation_dir}")
    return _seed_aviation_examples(aviation_dir, db_url)


if __name__ == "__main__":
    sys.exit(main())
