"""
One-time bootstrap: map existing Magento images to magento_media_map.
CLI: python -m app.jobs.magento_media_bootstrap --connection-id X --page-size N [--dry-run]
"""

from __future__ import annotations

import argparse
import hashlib
import json
import logging
import sys
from typing import Optional

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

MAGENTO_URL_PREFIX = "magento://"


def _canonical_json(obj) -> str:
    if obj is None:
        return "null"
    return json.dumps(obj, sort_keys=True, default=str)


def _media_hash(media_files: list) -> str:
    return hashlib.sha256(_canonical_json(media_files).encode()).hexdigest()


def run_bootstrap(
    connection_id: int,
    *,
    page_size: int = 50,
    dry_run: bool = False,
) -> dict:
    from db.session import get_session
    from db.magento_repositories import (
        SqlAlchemyMagentoConnectionRepository,
        SqlAlchemyMagentoMediaMapRepository,
        SqlAlchemyMagentoCatalogStateRepository,
    )
    from magento.oauth_client import MagentoOAuthClient, build_magento_oauth_kwargs
    from magento.magento_api import MagentoRestClient

    mapped = 0
    skus_done = 0
    errors = 0

    with get_session() as session:
        conn_repo = SqlAlchemyMagentoConnectionRepository(session)
        media_repo = SqlAlchemyMagentoMediaMapRepository(session)
        catalog_repo = SqlAlchemyMagentoCatalogStateRepository(session)
        conn = conn_repo.get_for_sync(connection_id)
        if not conn:
            return {"status": "failed", "error": "Connection not found", "mapped": 0}

        oauth = MagentoOAuthClient(**build_magento_oauth_kwargs(conn))
        api = MagentoRestClient(oauth)
        current_page = 1
        while True:
            status, items, total, err = api.list_products(
                page_size=page_size, current_page=current_page
            )
            if status != 200 or err:
                logger.error("Bootstrap list failed: HTTP %s %s", status, err)
                return {
                    "status": "failed",
                    "error": err or f"HTTP {status}",
                    "mapped": mapped,
                    "skus_done": skus_done,
                }
            if not items:
                break
            for p in items:
                if not isinstance(p, dict):
                    continue
                sku = p.get("sku")
                if not sku or not str(sku).strip():
                    continue
                try:
                    media_entries = p.get("media_gallery_entries") or []
                    media_files = []
                    for m in media_entries:
                        if isinstance(m, dict):
                            f = m.get("file") or ""
                            eid = m.get("id")
                            media_files.append({
                                "id": eid,
                                "file": f,
                                "types": m.get("types") or [],
                                "position": m.get("position", 0),
                                "disabled": m.get("disabled", False),
                            })
                    media_files.sort(key=lambda x: (x.get("position", 0), x.get("id") or 0))
                    m_hash = _media_hash(media_files) if media_files else None
                    if not dry_run and media_files:
                        catalog_repo.upsert_catalog_state(
                            connection_id,
                            sku,
                            media_files=media_files,
                            media_hash=m_hash,
                        )
                    skus_done += 1
                    for m in media_files:
                        f = m.get("file") or ""
                        eid = m.get("id")
                        if not f:
                            continue
                        remote_url = f"{MAGENTO_URL_PREFIX}{f}"
                        if not dry_run:
                            media_repo.upsert(
                                connection_id,
                                sku,
                                remote_url,
                                content_sha256=None,
                                magento_entry_id=int(eid) if eid is not None else None,
                                magento_file=f,
                            )
                        mapped += 1
                except Exception as e:
                    logger.exception("Bootstrap failed for %s: %s", sku, e)
                    errors += 1
            if total is not None and current_page * page_size >= total:
                break
            current_page += 1
        if not dry_run:
            session.commit()
    return {
        "status": "success",
        "mapped": mapped,
        "skus_done": skus_done,
        "errors": errors,
        "dry_run": dry_run,
    }


def main() -> int:
    parser = argparse.ArgumentParser(description="Bootstrap Magento media map from existing images")
    parser.add_argument("--connection-id", type=int, required=True)
    parser.add_argument("--page-size", type=int, default=50)
    parser.add_argument("--dry-run", action="store_true")
    args = parser.parse_args()
    result = run_bootstrap(
        args.connection_id,
        page_size=args.page_size,
        dry_run=args.dry_run,
    )
    if result.get("status") == "failed":
        print(result.get("error", "unknown"), file=sys.stderr)
        return 1
    print(
        f"Mapped {result.get('mapped', 0)} media entries, "
        f"{result.get('skus_done', 0)} SKUs processed"
        + (" (dry-run)" if result.get("dry_run") else "")
    )
    return 0


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