from datetime import datetime, timezone

from db.collection_path_guard import (
    ORPHAN_TIER_EMPTY_UNLINKED,
    ORPHAN_TIER_REVIEW,
    ORPHAN_TIER_TEST,
    list_orphan_remote_collections,
    list_orphan_shopify_collections,
)
from db.master_taxonomy_remote_purge import purge_remote_catalog_targets
from db.models import (
    MasterProduct,
    MasterTaxonomyChannelLink,
    MasterTaxonomyNode,
    ShopifyCollectionRegistry,
    ShopifyConnection,
)


def _ensure_shopify_connection(session):
    if session.get(ShopifyConnection, 1) is None:
        session.add(
            ShopifyConnection(
                id=1,
                shop_code="shopify-pb",
                shop_domain="pb.myshopify.com",
                admin_access_token="tok",
                status="active",
            )
        )
        session.flush()


def _add_shopify_collection(session, *, collection_id, title, handle="", ctype="manual", product_count=0):
    _ensure_shopify_connection(session)
    session.add(
        ShopifyCollectionRegistry(
            connection_id=1,
            shop_code="shopify-pb",
            collection_id=collection_id,
            handle=handle,
            title=title,
            collection_type=ctype,
            product_count=product_count,
            fetched_at=datetime.now(timezone.utc),
        )
    )


def _seed_known_collection(session):
    session.add(
        MasterProduct(
            sku="ASW-B15",
            name="Base",
            category_l1="Kitchen Cabinets",
            collection="Anna Snow White",
            row_hash="h1",
            is_active=True,
        )
    )


def test_orphan_shopify_classifies_test_junk(catalog_intent_session):
    session = catalog_intent_session
    _seed_known_collection(session)
    _add_shopify_collection(
        session,
        collection_id="gid://shopify/Collection/1",
        title="Anna Snow White Testing",
        handle="anna-snow-white-copy",
    )
    session.flush()

    orphans = list_orphan_shopify_collections(session, connection_id=1)
    by_id = {row["remote_id"]: row for row in orphans}
    assert by_id["gid://shopify/Collection/1"]["orphan_tier"] == ORPHAN_TIER_TEST


def test_orphan_shopify_classifies_custom_smart_collection_as_test(catalog_intent_session):
    session = catalog_intent_session
    _add_shopify_collection(
        session,
        collection_id="gid://shopify/Collection/2",
        title="custom-smart-collection",
        handle="custom-smart-collection",
    )
    session.flush()

    orphans = list_orphan_shopify_collections(session, connection_id=1)
    assert orphans[0]["orphan_tier"] == ORPHAN_TIER_TEST


def test_orphan_shopify_empty_unlinked_tier(catalog_intent_session):
    session = catalog_intent_session
    _add_shopify_collection(
        session,
        collection_id="gid://shopify/Collection/3",
        title="Cooper Slate Gray",
        handle="cooper-slate-gray",
    )
    session.flush()

    orphans = list_orphan_shopify_collections(session, connection_id=1)
    tiers = {row["remote_id"]: row["orphan_tier"] for row in orphans}
    assert tiers["gid://shopify/Collection/3"] == ORPHAN_TIER_EMPTY_UNLINKED


def test_orphan_shopify_review_when_has_products(catalog_intent_session):
    session = catalog_intent_session
    _add_shopify_collection(
        session,
        collection_id="gid://shopify/Collection/4",
        title="Some Unmanaged Series",
        handle="some-unmanaged-series",
        product_count=42,
    )
    session.flush()

    orphans = list_orphan_shopify_collections(session, connection_id=1)
    assert orphans[0]["orphan_tier"] == ORPHAN_TIER_REVIEW


def test_orphan_shopify_protected_handle_excluded(catalog_intent_session):
    session = catalog_intent_session
    _add_shopify_collection(
        session,
        collection_id="gid://shopify/Collection/5",
        title="Home page",
        handle="frontpage",
    )
    session.flush()

    orphans = list_orphan_shopify_collections(session, connection_id=1)
    assert not orphans


def test_orphan_shopify_active_link_is_not_orphan(catalog_intent_session):
    session = catalog_intent_session
    node = MasterTaxonomyNode(
        node_kind="collection",
        code="anna-snow-white",
        name="Anna Snow White",
        path_slug="kitchen-cabinets/anna-snow-white",
        is_active=True,
    )
    session.add(node)
    session.flush()
    session.add(
        MasterTaxonomyChannelLink(
            taxonomy_node_id=node.id,
            channel_code="shopify",
            connection_id=1,
            taxonomy_kind="collection",
            remote_id="gid://shopify/Collection/6",
            is_active=True,
        )
    )
    _add_shopify_collection(
        session,
        collection_id="gid://shopify/Collection/6",
        title="Kitchen Cabinets Anna Snow White",
        handle="kitchen-cabinets-anna-snow-white",
        product_count=459,
    )
    session.flush()

    orphans = list_orphan_shopify_collections(session, connection_id=1)
    assert not any(row["remote_id"] == "gid://shopify/Collection/6" for row in orphans)


def test_orphan_shopify_inactive_link_becomes_orphan(catalog_intent_session):
    session = catalog_intent_session
    node = MasterTaxonomyNode(
        node_kind="collection",
        code="stale",
        name="Stale",
        path_slug="kitchen-cabinets/stale",
        is_active=False,
    )
    session.add(node)
    session.flush()
    session.add(
        MasterTaxonomyChannelLink(
            taxonomy_node_id=node.id,
            channel_code="shopify",
            connection_id=1,
            taxonomy_kind="collection",
            remote_id="gid://shopify/Collection/7",
            is_active=False,
        )
    )
    _add_shopify_collection(
        session,
        collection_id="gid://shopify/Collection/7",
        title="Stale Testing Collection",
        handle="stale-testing",
    )
    session.flush()

    orphans = list_orphan_shopify_collections(session, connection_id=1)
    assert any(row["remote_id"] == "gid://shopify/Collection/7" for row in orphans)


def test_list_orphan_remote_collections_uses_compat_id(catalog_intent_session):
    session = catalog_intent_session
    _add_shopify_collection(
        session,
        collection_id="gid://shopify/Collection/8",
        title="Cooper Slate Gray Testing",
        handle="cooper-slate-gray-copy1",
    )
    session.flush()

    orphans = list_orphan_remote_collections(
        session,
        shopify_connection_id=1_000_001,
    )
    assert any(row["remote_id"] == "gid://shopify/Collection/8" for row in orphans)


class _FakeShopifyClient:
    def __init__(self, *, not_found_ids=None):
        self.not_found_ids = set(not_found_ids or [])
        self.deleted = []

    def graphql(self, query, variables):
        collection_id = variables["input"]["id"]
        if collection_id in self.not_found_ids:
            return {"collectionDelete": {"userErrors": [{"field": ["id"], "message": "Collection does not exist"}]}}
        self.deleted.append(collection_id)
        return {"collectionDelete": {"deletedCollectionId": collection_id, "userErrors": []}}


def test_purge_treats_missing_shopify_collection_as_already_deleted(catalog_intent_session):
    session = catalog_intent_session
    node = MasterTaxonomyNode(
        node_kind="collection",
        code="dead",
        name="Dead",
        path_slug="kitchen-cabinets/dead",
        is_active=False,
    )
    session.add(node)
    session.flush()
    link = MasterTaxonomyChannelLink(
        taxonomy_node_id=node.id,
        channel_code="shopify",
        connection_id=1,
        taxonomy_kind="collection",
        remote_id="gid://shopify/Collection/dead",
        is_active=True,
    )
    session.add(link)
    session.flush()

    client = _FakeShopifyClient(not_found_ids={"gid://shopify/Collection/dead"})
    stats = purge_remote_catalog_targets(
        targets=[
            {
                "channel_code": "shopify",
                "remote_id": "gid://shopify/Collection/dead",
                "name": "Dead",
            }
        ],
        shopify_client=client,
        dry_run=False,
        session=session,
    )
    assert stats["already_deleted"] == 1
    assert stats["shopify_deleted"] == 1
    assert not stats["errors"]
    assert stats["links_deactivated"] == 1
    session.refresh(link)
    assert link.is_active is False


def test_purge_deletes_and_deactivates_link(catalog_intent_session):
    session = catalog_intent_session
    node = MasterTaxonomyNode(
        node_kind="collection",
        code="live",
        name="Live",
        path_slug="kitchen-cabinets/live",
        is_active=False,
    )
    session.add(node)
    session.flush()
    link = MasterTaxonomyChannelLink(
        taxonomy_node_id=node.id,
        channel_code="shopify",
        connection_id=1,
        taxonomy_kind="collection",
        remote_id="gid://shopify/Collection/live",
        is_active=True,
    )
    session.add(link)
    session.flush()

    client = _FakeShopifyClient()
    stats = purge_remote_catalog_targets(
        targets=[
            {
                "channel_code": "shopify",
                "remote_id": "gid://shopify/Collection/live",
                "name": "Live",
            }
        ],
        shopify_client=client,
        dry_run=False,
        session=session,
    )
    assert stats["shopify_deleted"] == 1
    assert stats["already_deleted"] == 0
    assert client.deleted == ["gid://shopify/Collection/live"]
    session.refresh(link)
    assert link.is_active is False
