from __future__ import annotations

import json
import re
from pathlib import Path

from src.domain.email.catalog_contract import (
    CLOUD_SUPPORTED_TEMPLATE_IDS,
    canonical_catalog_json,
    catalog_fingerprint,
    fingerprint_payload,
)

ROOT = Path(__file__).resolve().parents[1]
CLOUD_META = ROOT.parent / "P2HSCloud" / "apps" / "pc-gateway" / "src" / "lib" / "email-template-catalog-meta.ts"


def _cloud_meta() -> dict[str, dict]:
    text = CLOUD_META.read_text(encoding="utf-8")
    pattern = re.compile(
        r'"([^"]+)":\s*\{\s*optional:\s*(?:true|false),\s*'
        r'archetype:\s*"([^"]+)",\s*defaultProfile:\s*"([^"]+)",\s*'
        r'requiredPlaceholders:\s*\[[^]]*\],\s*requiredVariables:\s*\[([^]]*)\],\s*'
        r'optionalVariables:\s*\{([^}]*)\}',
        re.S,
    )
    result = {}
    for match in pattern.finditer(text):
        key, archetype, profile, required_raw, optional_raw = match.groups()
        result[key] = {
            "id": key,
            "version": 1,
            "archetype": archetype,
            "default_profile": profile,
            "required_variables": sorted(re.findall(r'"([a-z_]+)"', required_raw)),
            "optional_variables": {
                name: value
                for name, value in re.findall(r'([a-z_]+):\s*"([^"]*)"', optional_raw)
            },
        }
    return result


def test_canonical_serialization_is_order_independent() -> None:
    first = json.loads(canonical_catalog_json())
    reordered = {"profiles": first["profiles"], "templates": list(reversed(first["templates"])), "catalog_version": 1, "schema_version": 1}
    assert fingerprint_payload(first) == fingerprint_payload(reordered)


def test_cloud_mirrors_shared_core_template_contract() -> None:
    cloud = _cloud_meta()
    core = json.loads(canonical_catalog_json())
    assert sorted(cloud) == sorted(CLOUD_SUPPORTED_TEMPLATE_IDS)
    assert sorted(cloud.values(), key=lambda item: item["id"]) == sorted(core["templates"], key=lambda item: item["id"])


def test_semantic_changes_change_fingerprint_but_branding_does_not() -> None:
    payload = json.loads(canonical_catalog_json())
    baseline = catalog_fingerprint()
    payload["templates"][0]["archetype"] = "action" if payload["templates"][0]["archetype"] != "action" else "security"
    changed = fingerprint_payload(payload)
    assert changed != baseline
    payload["branding"] = {"app_name": "Acme", "accent": "#fff"}
    branded = fingerprint_payload(payload)
    payload.pop("branding")
    restored = fingerprint_payload(payload)
    assert branded == restored
    assert catalog_fingerprint() == baseline
