"""Bootstrap SKU linking and channel taxonomy assignments for master-catalog push."""

from __future__ import annotations

import argparse
from typing import Any, Dict, Optional

from db.channel_sku_mapping import (
    auto_link_skus_after_pull,
    bootstrap_from_magento_catalog,
    bootstrap_identity_mappings,
)
from db.compat_connections import compat_connection_id
from db.models import ChannelConnection, MagentoConnection, ShopifyConnection
from db.product_channel_taxonomy import (
    auto_assign_from_path_mappings,
    auto_assign_shopify_product_categories,
)
from db.session import get_session
from shopify.connections import build_client, get_active_connection
from shopify.taxonomy_sync import pull_shopify_taxonomy_registry
from sqlalchemy import select


def _active_connections(session) -> Dict[str, Dict[str, Any]]:
    out: Dict[str, Dict[str, Any]] = {}
    magento = session.scalars(select(MagentoConnection).order_by(MagentoConnection.id)).first()
    if magento:
        out["magento"] = {
            "native_id": magento.id,
            "connection_id": compat_connection_id("magento", magento.id),
        }
    shopify = session.scalars(
        select(ShopifyConnection).where(ShopifyConnection.status == "active").order_by(ShopifyConnection.id)
    ).first()
    if shopify is None:
        shopify = session.scalars(select(ShopifyConnection).order_by(ShopifyConnection.id)).first()
    if shopify:
        out["shopify"] = {
            "native_id": shopify.id,
            "connection_id": compat_connection_id("shopify", shopify.id),
        }
    plytix = session.scalars(
        select(ChannelConnection)
        .where(ChannelConnection.channel_type == "plytix")
        .order_by(ChannelConnection.id)
    ).first()
    if plytix:
        out["plytix"] = {
            "native_id": plytix.id,
            "connection_id": compat_connection_id("generic", plytix.id),
        }
    return out


def run_catalog_link_bootstrap(
    *,
    link_magento: bool = True,
    link_shopify: bool = True,
    link_plytix: bool = True,
    pull_shopify_taxonomy: bool = True,
    pull_shopify_collections: bool = True,
    auto_assign_taxonomy: bool = True,
    only_assigned: bool = True,
    dry_run: bool = False,
    magento_connection_id: Optional[int] = None,
    shopify_connection_id: Optional[int] = None,
) -> Dict[str, Any]:
    """Link SKUs across channels, pull Shopify taxonomy, and seed category assignments."""
    summary: Dict[str, Any] = {"channels": {}, "shopify_taxonomy": None, "shopify_collections": None, "taxonomy_assignments": {}}

    with get_session() as session:
        connections = _active_connections(session)

        if link_magento:
            magento = connections.get("magento")
            native_id = magento_connection_id or (magento["native_id"] if magento else None)
            compat_id = magento["connection_id"] if magento else None
            channel_result: Dict[str, Any] = {}
            if native_id and not dry_run:
                channel_result["bootstrap_magento"] = bootstrap_from_magento_catalog(
                    session,
                    native_id,
                    only_assigned=only_assigned,
                )
            if compat_id:
                channel_result["link_from_remote"] = _link_channel(
                    session,
                    channel_type="magento",
                    channel_code="magento",
                    compat_connection_id=compat_id,
                    native_connection_id=native_id,
                    only_assigned=only_assigned,
                    dry_run=dry_run,
                )
            summary["channels"]["magento"] = channel_result

        if link_shopify:
            shopify = connections.get("shopify")
            native_id = shopify_connection_id or (shopify["native_id"] if shopify else None)
            compat_id = shopify["connection_id"] if shopify else None
            channel_result = {}
            if compat_id:
                channel_result["link_from_remote"] = _link_channel(
                    session,
                    channel_type="shopify",
                    channel_code="shopify",
                    compat_connection_id=compat_id,
                    native_connection_id=native_id,
                    only_assigned=only_assigned,
                    dry_run=dry_run,
                )
            summary["channels"]["shopify"] = channel_result

        if link_plytix:
            plytix = connections.get("plytix")
            compat_id = plytix["connection_id"] if plytix else None
            if compat_id:
                summary["channels"]["plytix"] = {
                    "bootstrap_identity": bootstrap_identity_mappings(session, "plytix", only_assigned=only_assigned)
                    if not dry_run
                    else {"dry_run": True},
                    "link_from_remote": _link_channel(
                        session,
                        channel_type="plytix",
                        channel_code="plytix",
                        compat_connection_id=compat_id,
                        native_connection_id=None,
                        only_assigned=only_assigned,
                        dry_run=dry_run,
                    ),
                }

        if pull_shopify_taxonomy and not dry_run:
            connection = None
            if shopify_connection_id:
                from db.models import ShopifyConnection

                connection = session.get(ShopifyConnection, shopify_connection_id)
            if connection is None:
                connection = get_active_connection(session)
            if connection is not None:
                client = build_client(connection)
                summary["shopify_taxonomy"] = pull_shopify_taxonomy_registry(session, client)

        if pull_shopify_collections and not dry_run:
            connection = None
            if shopify_connection_id:
                from db.models import ShopifyConnection

                connection = session.get(ShopifyConnection, shopify_connection_id)
            if connection is None:
                connection = get_active_connection(session)
            if connection is not None:
                from shopify.collection_sync import pull_shopify_collections

                client = build_client(connection)
                summary["shopify_collections"] = pull_shopify_collections(
                    client,
                    shop_code=connection.shop_code,
                    connection_id=connection.id,
                    session=session,
                )

        if auto_assign_taxonomy and not dry_run:
            magento_native = magento_connection_id
            if not magento_native and connections.get("magento"):
                magento_native = connections["magento"]["native_id"]
            shopify_native = shopify_connection_id
            if not shopify_native and connections.get("shopify"):
                shopify_native = connections["shopify"]["native_id"]

            summary["taxonomy_assignments"]["magento_path_map"] = auto_assign_from_path_mappings(
                session,
                channel_code="magento",
                connection_id=magento_native,
                only_assigned=only_assigned,
            )
            summary["taxonomy_assignments"]["shopify_path_map"] = auto_assign_from_path_mappings(
                session,
                channel_code="shopify",
                connection_id=shopify_native,
                only_assigned=only_assigned,
            )
            summary["taxonomy_assignments"]["shopify_product_category"] = auto_assign_shopify_product_categories(
                session,
                connection_id=shopify_native,
                only_assigned=only_assigned,
            )

        if not dry_run:
            session.commit()

    summary["status"] = "ok"
    summary["dry_run"] = dry_run
    return summary


def _link_channel(
    session,
    *,
    channel_type: str,
    channel_code: str,
    compat_connection_id: int,
    native_connection_id: Optional[int],
    only_assigned: bool,
    dry_run: bool,
) -> Dict[str, Any]:
    if dry_run:
        from db.channel_sku_mapping import build_reconciliation_report, reconcile_connection_id_for_channel

        return build_reconciliation_report(
            session,
            channel_code,
            connection_id=reconcile_connection_id_for_channel(
                channel_code,
                compat_connection_id=compat_connection_id,
                native_connection_id=native_connection_id,
            ),
            only_assigned=only_assigned,
        )
    return auto_link_skus_after_pull(
        session,
        channel_type=channel_type,
        channel_code=channel_code,
        compat_connection_id=compat_connection_id,
        native_connection_id=native_connection_id,
        only_assigned=only_assigned,
    )


def main() -> None:
    parser = argparse.ArgumentParser(description="Link channel SKUs and bootstrap taxonomy assignments")
    parser.add_argument("--dry-run", action="store_true")
    parser.add_argument("--all-assigned", action="store_true", help="Include all active masters, not only assigned")
    parser.add_argument("--skip-link", action="store_true")
    parser.add_argument("--skip-taxonomy-pull", action="store_true")
    parser.add_argument("--skip-collections-pull", action="store_true")
    parser.add_argument("--skip-taxonomy-assign", action="store_true")
    parser.add_argument("--magento-connection-id", type=int, default=None)
    parser.add_argument("--shopify-connection-id", type=int, default=None)
    args = parser.parse_args()

    result = run_catalog_link_bootstrap(
        link_magento=not args.skip_link,
        link_shopify=not args.skip_link,
        link_plytix=not args.skip_link,
        pull_shopify_taxonomy=not args.skip_taxonomy_pull,
        pull_shopify_collections=not args.skip_collections_pull,
        auto_assign_taxonomy=not args.skip_taxonomy_assign,
        only_assigned=not args.all_assigned,
        dry_run=args.dry_run,
        magento_connection_id=args.magento_connection_id,
        shopify_connection_id=args.shopify_connection_id,
    )
    print(result)


if __name__ == "__main__":
    main()
