"""Bridge master collection registry ↔ landing pages ↔ channel taxonomy."""

from __future__ import annotations

from typing import Any, Dict, Optional

from sqlalchemy import select
from sqlalchemy.orm import Session

from channel.url_canonical import normalize_plp_path
from db.channel_listing_path import upsert_listing_path
from db.channel_taxonomy import upsert_taxonomy_mapping
from db.collection_landing_pages import canonical_collection
from db.models import CollectionLandingPage, MasterCollectionRegistry


def link_collection_registry_to_landing(
    session: Session,
    *,
    path_slug: Optional[str] = None,
    registry_id: Optional[int] = None,
) -> Dict[str, Any]:
    """Align collection_landing_page.collection_registry_id with registry row."""
    registry = None
    if registry_id is not None:
        registry = session.get(MasterCollectionRegistry, int(registry_id))
    slug = normalize_plp_path(path_slug or (registry.path_slug if registry else ""))
    if registry is None and slug:
        registry = session.scalar(
            select(MasterCollectionRegistry).where(MasterCollectionRegistry.path_slug == slug).limit(1)
        )
    if registry is None:
        raise ValueError("Collection registry not found")

    landing = None
    if slug:
        landing = session.scalar(select(CollectionLandingPage).where(CollectionLandingPage.path_slug == slug).limit(1))
    if landing is None:
        landing = session.scalar(
            select(CollectionLandingPage)
            .where(CollectionLandingPage.collection_registry_id == registry.id)
            .limit(1)
        )
    if landing is None and registry.path_slug:
        landing = session.scalar(
            select(CollectionLandingPage).where(CollectionLandingPage.path_slug == registry.path_slug).limit(1)
        )

    if landing is None:
        return {"linked": False, "registry": _registry_dict(registry), "landing_page": None}

    if not registry.path_slug:
        registry.path_slug = landing.path_slug
    landing.collection_registry_id = registry.id
    if not landing.collection and registry.name:
        landing.collection = registry.name

    upsert_listing_path(
        session,
        path_slug=landing.path_slug,
        title=landing.title or registry.name,
        path_kind="collection",
        parent_path_slug=landing.parent_path_slug,
        hub_path_slug=normalize_plp_path(landing.category_l1 or ""),
        notes="linked from collection registry bridge",
    )
    session.flush()
    return {
        "linked": True,
        "registry": _registry_dict(registry),
        "landing_page": {"path_slug": landing.path_slug, "title": landing.title},
    }


def sync_channel_taxonomy_mapping_from_registry(
    session: Session,
    *,
    registry_id: int,
    channel_code: str,
    remote_id: str,
    connection_id: Optional[int] = None,
    taxonomy_kind: str = "collection",
    remote_path: Optional[str] = None,
) -> Dict[str, Any]:
    registry = session.get(MasterCollectionRegistry, int(registry_id))
    if registry is None:
        raise ValueError("Collection registry not found")
    master_path_key = registry.path_slug or registry.code
    row = upsert_taxonomy_mapping(
        session,
        channel_code=channel_code,
        master_path_key=master_path_key,
        channel_remote_id=str(remote_id),
        channel_taxonomy_kind=taxonomy_kind,
        connection_id=connection_id,
        channel_handle_or_path=remote_path or registry.name,
        master_collection=registry.name,
        is_active=True,
    )
    return {"mapping": row, "master_path_key": master_path_key}


def describe_registry_consistency(
    session: Session,
    *,
    path_slug: str,
) -> Dict[str, Any]:
    slug = normalize_plp_path(path_slug)
    landing = session.scalar(select(CollectionLandingPage).where(CollectionLandingPage.path_slug == slug).limit(1))
    registry = None
    if landing and landing.collection_registry_id:
        registry = session.get(MasterCollectionRegistry, int(landing.collection_registry_id))
    if registry is None:
        registry = session.scalar(
            select(MasterCollectionRegistry).where(MasterCollectionRegistry.path_slug == slug).limit(1)
        )
    issues = []
    if landing and registry:
        if canonical_collection(landing.collection) != canonical_collection(registry.name):
            issues.append("collection_name_mismatch")
        if landing.collection_registry_id != registry.id:
            issues.append("landing_registry_fk_mismatch")
    elif landing and not registry:
        issues.append("registry_missing")
    elif registry and not landing:
        issues.append("landing_missing")
    return {
        "path_slug": slug,
        "registry": _registry_dict(registry) if registry else None,
        "landing_page": {"path_slug": landing.path_slug, "title": landing.title} if landing else None,
        "issues": issues,
        "consistent": not issues,
    }


def _registry_dict(row: MasterCollectionRegistry) -> Dict[str, Any]:
    return {
        "id": row.id,
        "code": row.code,
        "name": row.name,
        "path_slug": row.path_slug,
        "brand_id": row.brand_id,
        "family_id": row.family_id,
    }
