from pathlib import Path
import shutil
import uuid

from app.jobs.cleanup_taxonomy_pollution_from_audit import cleanup_taxonomy_pollution_from_audit
from db.models import MasterTaxonomyChannelLink, MasterTaxonomyNode, MasterTaxonomyPathAlias


def _write_audit_dir(files: dict[str, str]) -> Path:
    path = Path("tests") / f"_tmp_taxonomy_audit_{uuid.uuid4().hex}"
    path.mkdir(parents=True, exist_ok=True)
    for name, content in files.items():
        (path / name).write_text(content, encoding="utf-8")
    return path


def test_cleanup_deletes_inactive_taxonomy_nodes_from_inactive_link_audit(catalog_intent_session):
    node = MasterTaxonomyNode(
        node_kind="collection",
        code="stone-gray",
        name="Stone Gray",
        path_slug="kitchen-cabinets/stone-gray",
        is_active=False,
    )
    catalog_intent_session.add(node)
    catalog_intent_session.flush()

    link = MasterTaxonomyChannelLink(
        taxonomy_node_id=node.id,
        channel_code="magento",
        connection_id=2,
        taxonomy_kind="collection",
        remote_id="77",
        is_active=True,
    )
    alias = MasterTaxonomyPathAlias(
        alias_path_slug="kitchen-cabinets/stone-grey",
        canonical_node_id=node.id,
    )
    catalog_intent_session.add_all([link, alias])
    catalog_intent_session.flush()

    audit_dir = _write_audit_dir(
        {
            "links_to_inactive_taxonomy_nodes.csv": (
                "id,taxonomy_node_id,path_slug\n"
                f"{link.id},{node.id},{node.path_slug}\n"
            )
        }
    )

    try:
        summary = cleanup_taxonomy_pollution_from_audit(
            catalog_intent_session,
            audit_dir=audit_dir,
            dry_run=False,
        )
        catalog_intent_session.flush()
    finally:
        shutil.rmtree(audit_dir, ignore_errors=True)

    assert catalog_intent_session.get(MasterTaxonomyChannelLink, link.id) is None
    assert catalog_intent_session.get(MasterTaxonomyPathAlias, alias.id) is None
    assert catalog_intent_session.get(MasterTaxonomyNode, node.id) is None
    assert summary["steps"]["master_taxonomy_channel_links"]["deactivated"] == 1
    assert summary["steps"]["master_taxonomy_node"]["deleted_nodes"] == 1
    assert summary["steps"]["master_taxonomy_node"]["deleted_links"] == 1
    assert summary["steps"]["master_taxonomy_node"]["deleted_aliases"] == 1


def test_cleanup_blocks_inactive_taxonomy_node_delete_when_child_is_not_in_plan(catalog_intent_session):
    parent = MasterTaxonomyNode(
        node_kind="category",
        code="parent",
        name="Parent",
        path_slug="kitchen-cabinets/parent",
        is_active=False,
    )
    catalog_intent_session.add(parent)
    catalog_intent_session.flush()

    child = MasterTaxonomyNode(
        parent_id=parent.id,
        node_kind="collection",
        code="child",
        name="Child",
        path_slug="kitchen-cabinets/parent/child",
        is_active=False,
    )
    catalog_intent_session.add(child)
    catalog_intent_session.flush()

    audit_dir = _write_audit_dir(
        {
            "inactive_master_taxonomy_nodes.csv": (
                "id,path_slug\n"
                f"{parent.id},{parent.path_slug}\n"
            )
        }
    )

    try:
        summary = cleanup_taxonomy_pollution_from_audit(
            catalog_intent_session,
            audit_dir=audit_dir,
            dry_run=False,
        )
        catalog_intent_session.flush()
    finally:
        shutil.rmtree(audit_dir, ignore_errors=True)

    assert catalog_intent_session.get(MasterTaxonomyNode, parent.id) is not None
    assert catalog_intent_session.get(MasterTaxonomyNode, child.id) is not None
    assert summary["steps"]["master_taxonomy_node"]["deleted_nodes"] == 0
    assert summary["steps"]["master_taxonomy_node"]["blocked_by_children"] == 1


def test_cleanup_deletes_inactive_taxonomy_nodes_from_explicit_node_audit(catalog_intent_session):
    node = MasterTaxonomyNode(
        node_kind="collection",
        code="pearl-white",
        name="Pearl White",
        path_slug="kitchen-cabinets/pearl-white",
        is_active=False,
    )
    catalog_intent_session.add(node)
    catalog_intent_session.flush()

    audit_dir = _write_audit_dir(
        {
            "inactive_master_taxonomy_nodes.csv": (
                "id,path_slug\n"
                f"{node.id},{node.path_slug}\n"
            )
        }
    )

    try:
        summary = cleanup_taxonomy_pollution_from_audit(
            catalog_intent_session,
            audit_dir=audit_dir,
            dry_run=False,
        )
        catalog_intent_session.flush()
    finally:
        shutil.rmtree(audit_dir, ignore_errors=True)

    assert catalog_intent_session.get(MasterTaxonomyNode, node.id) is None
    assert summary["steps"]["master_taxonomy_node"]["deleted_nodes"] == 1


def test_cleanup_deletes_inactive_taxonomy_nodes_directly_from_db(catalog_intent_session):
    node = MasterTaxonomyNode(
        node_kind="collection",
        code="mist-gray",
        name="Mist Gray",
        path_slug="kitchen-cabinets/mist-gray",
        is_active=False,
    )
    catalog_intent_session.add(node)
    catalog_intent_session.flush()

    link = MasterTaxonomyChannelLink(
        taxonomy_node_id=node.id,
        channel_code="magento",
        connection_id=2,
        taxonomy_kind="collection",
        remote_id="88",
        is_active=True,
    )
    catalog_intent_session.add(link)
    catalog_intent_session.flush()

    summary = cleanup_taxonomy_pollution_from_audit(
        catalog_intent_session,
        audit_dir="tests",
        dry_run=False,
        db_inactive_taxonomy_nodes=True,
        inactive_node_path_prefixes=["kitchen-cabinets"],
    )
    catalog_intent_session.flush()

    assert catalog_intent_session.get(MasterTaxonomyChannelLink, link.id) is None
    assert catalog_intent_session.get(MasterTaxonomyNode, node.id) is None
    assert summary["steps"]["master_taxonomy_channel_links"]["deactivated"] == 1
    assert summary["steps"]["master_taxonomy_node"]["deleted_nodes"] == 1
