"""Persistence helpers for Deal Desk profiles, contexts, and generated drafts."""

from __future__ import annotations

import json
import os
import re
from collections.abc import Callable
from pathlib import Path
from typing import Any

try:
    import yaml
except Exception:  # pragma: no cover
    yaml = None  # type: ignore[assignment]

from g_gremlin.paths import resolve_gremlin_home

from .config import DEFAULT_CONFIG_PATH, DealDeskConfig, load_dealdesk_config
from .context import DealContextV1
from .history import CloseCertificationRunV1
from .integrity import QuoteDocumentFingerprintV1
from .profiles import DealPatternProfileV1, PatternUpdateEventV1, QuoteEnvironmentProfileV1
from .reconciliation import ReconciliationPacketV1
from .quote_plan import QuoteDraftPlanV1
from .triggers import PostCloseTriggerRunV1


_NON_ALNUM_RE = re.compile(r"[^A-Za-z0-9._-]+")


def resolve_dealdesk_state_dir(state_dir: str | Path | None = None) -> Path:
    if state_dir not in (None, ""):
        return Path(state_dir).expanduser().resolve()

    env_state_dir = os.getenv("G_GREMLIN_STATE_DIR", "").strip()
    if env_state_dir:
        return Path(env_state_dir).expanduser().resolve()
    return (resolve_gremlin_home() / "autopilot").resolve()


def _safe_key(value: str | None, *, default: str) -> str:
    text = str(value or "").strip()
    if not text:
        return default
    cleaned = _NON_ALNUM_RE.sub("-", text)
    cleaned = cleaned.strip("._-")
    return cleaned or default


def _org_storage_key(*, crm_org_id: str | None, org_alias: str | None) -> str:
    if crm_org_id not in (None, ""):
        return _safe_key(str(crm_org_id), default="unknown-org")
    if org_alias not in (None, ""):
        return _safe_key(str(org_alias), default="unknown-org")
    return "unknown-org"


def _write_json(path: Path, payload: dict[str, Any]) -> Path:
    path.parent.mkdir(parents=True, exist_ok=True)
    with path.open("w", encoding="utf-8") as handle:
        json.dump(payload, handle, indent=2, sort_keys=True)
    return path


def _read_json(path: Path) -> dict[str, Any]:
    with path.open(encoding="utf-8") as handle:
        payload = json.load(handle)
    return payload if isinstance(payload, dict) else {}


def _write_config_payload(path: Path, config: DealDeskConfig) -> Path:
    path.parent.mkdir(parents=True, exist_ok=True)
    payload = config.model_dump(exclude_none=False)
    if yaml is not None:
        with path.open("w", encoding="utf-8") as handle:
            yaml.safe_dump(payload, handle, sort_keys=False)
        return path
    json_path = path.with_suffix(".json")
    return _write_json(json_path, payload)


def _read_config_payload(path: Path) -> DealDeskConfig | None:
    if not path.exists():
        return None
    if path.suffix.lower() in {".yaml", ".yml"} and yaml is not None:
        with path.open(encoding="utf-8") as handle:
            payload = yaml.safe_load(handle) or {}
        if isinstance(payload, dict):
            return DealDeskConfig.model_validate(payload)
        return None
    if path.suffix.lower() == ".json":
        return DealDeskConfig.model_validate(_read_json(path))
    return None


class DealDeskStore:
    def __init__(self, state_dir: str | Path | None = None) -> None:
        self.state_dir = resolve_dealdesk_state_dir(state_dir)
        self.root = self.state_dir / "dealdesk"

    def save_quote_environment_profile(self, profile: QuoteEnvironmentProfileV1) -> Path:
        path = self._quote_environment_path(
            crm_org_id=profile.crm_org_id,
            org_alias=profile.org_alias,
        )
        return _write_json(path, profile.to_dict())

    def load_quote_environment_profile(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> QuoteEnvironmentProfileV1 | None:
        path = self._quote_environment_path(crm_org_id=crm_org_id, org_alias=org_alias)
        if not path.exists():
            return None
        return QuoteEnvironmentProfileV1.from_dict(_read_json(path))

    def save_deal_pattern_profile(self, profile: DealPatternProfileV1) -> Path:
        path = self._deal_pattern_path(
            crm_org_id=profile.crm_org_id,
            org_alias=profile.org_alias,
        )
        return _write_json(path, profile.to_dict())

    def load_deal_pattern_profile(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> DealPatternProfileV1 | None:
        path = self._deal_pattern_path(crm_org_id=crm_org_id, org_alias=org_alias)
        if not path.exists():
            return None
        return DealPatternProfileV1.from_dict(_read_json(path))

    def save_pattern_update_event(self, event: PatternUpdateEventV1) -> Path:
        org_key = _org_storage_key(crm_org_id=event.crm_org_id, org_alias=None)
        event_key = _safe_key(event.event_id, default="event")
        path = self.root / "events" / org_key / f"{event_key}.json"
        return _write_json(path, event.to_dict())

    def list_pattern_update_events(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> list[PatternUpdateEventV1]:
        org_key = _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias)
        root = self.root / "events" / org_key
        if not root.exists():
            return []
        events: list[PatternUpdateEventV1] = []
        for path in sorted(root.glob("*.json")):
            try:
                events.append(PatternUpdateEventV1.from_dict(_read_json(path)))
            except Exception:
                continue
        return events

    def save_context(self, context: DealContextV1) -> Path:
        path = self._context_path(
            crm_org_id=context.crm_org_id,
            org_alias=context.org_alias,
            opportunity_id=context.opportunity_id,
        )
        return _write_json(path, context.to_dict())

    def load_context(
        self,
        *,
        opportunity_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> DealContextV1 | None:
        path = self._context_path(
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            opportunity_id=opportunity_id,
        )
        if not path.exists():
            return None
        return DealContextV1.from_dict(_read_json(path))

    def list_contexts(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> list[DealContextV1]:
        root = self.root / "contexts"
        if not root.exists():
            return []
        if crm_org_id not in (None, "") or org_alias not in (None, ""):
            roots = [root / _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias)]
        else:
            roots = [path for path in sorted(root.iterdir()) if path.is_dir()]
        contexts: list[DealContextV1] = []
        for current_root in roots:
            if not current_root.exists():
                continue
            for path in sorted(current_root.glob("*.json")):
                try:
                    contexts.append(DealContextV1.from_dict(_read_json(path)))
                except Exception:
                    continue
        return contexts

    def save_reconciliation_packet(self, packet: ReconciliationPacketV1) -> Path:
        path = self.reconciliation_packet_path(
            opportunity_id=packet.opportunity_id,
            packet_id=packet.packet_id,
            crm_org_id=packet.crm_org_id,
            org_alias=packet.org_alias,
        )
        return _write_json(path, packet.to_dict())

    def save_quote_document_fingerprint(self, fingerprint: QuoteDocumentFingerprintV1) -> Path:
        path = self.quote_document_fingerprint_path(
            opportunity_id=fingerprint.opportunity_id,
            quote_id=fingerprint.quote_id,
            fingerprint_id=fingerprint.fingerprint_id,
            crm_org_id=fingerprint.crm_org_id,
            org_alias=fingerprint.org_alias,
        )
        return _write_json(path, fingerprint.to_dict())

    def save_close_certification_run(self, run: CloseCertificationRunV1) -> Path:
        path = self.close_certification_run_path(
            opportunity_id=run.opportunity_id,
            run_id=run.run_id,
            crm_org_id=run.crm_org_id,
            org_alias=run.org_alias,
        )
        return _write_json(path, run.to_dict())

    def save_post_close_trigger_run(self, run: PostCloseTriggerRunV1) -> Path:
        path = self.post_close_trigger_run_path(
            opportunity_id=run.opportunity_id,
            run_id=run.run_id,
            crm_org_id=run.crm_org_id,
            org_alias=run.org_alias,
        )
        return _write_json(path, run.to_dict())

    def list_post_close_trigger_runs(
        self,
        *,
        opportunity_id: str | None = None,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> list[PostCloseTriggerRunV1]:
        if opportunity_id not in (None, ""):
            roots = [
                self.post_close_trigger_run_dir(
                    opportunity_id=str(opportunity_id),
                    crm_org_id=crm_org_id,
                    org_alias=org_alias,
                )
            ]
        else:
            root = self.root / "post_close"
            if crm_org_id not in (None, "") or org_alias not in (None, ""):
                org_root = root / _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias)
                roots = [path for path in sorted(org_root.iterdir()) if path.is_dir()] if org_root.exists() else []
            else:
                roots = []
                if root.exists():
                    for org_root in sorted(root.iterdir()):
                        if not org_root.is_dir():
                            continue
                        roots.extend(path for path in sorted(org_root.iterdir()) if path.is_dir())
        runs: list[PostCloseTriggerRunV1] = []
        for current_root in roots:
            if not current_root.exists():
                continue
            for path in sorted(current_root.glob("*.json")):
                try:
                    runs.append(PostCloseTriggerRunV1.from_dict(_read_json(path)))
                except Exception:
                    continue
        return runs

    def load_post_close_trigger_run(
        self,
        *,
        run_id: str,
        opportunity_id: str | None = None,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> PostCloseTriggerRunV1 | None:
        normalized_run_id = str(run_id or "").strip()
        if not normalized_run_id:
            return None
        if opportunity_id not in (None, ""):
            path = self.post_close_trigger_run_path(
                opportunity_id=str(opportunity_id),
                run_id=normalized_run_id,
                crm_org_id=crm_org_id,
                org_alias=org_alias,
            )
            if path.exists():
                return PostCloseTriggerRunV1.from_dict(_read_json(path))
        if opportunity_id not in (None, ""):
            runs = self.list_post_close_trigger_runs(
                opportunity_id=str(opportunity_id),
                crm_org_id=crm_org_id,
                org_alias=org_alias,
            )
        else:
            runs = self.list_post_close_trigger_runs(
                crm_org_id=crm_org_id,
                org_alias=org_alias,
            )
        for item in runs:
            if item.run_id == normalized_run_id:
                return item
        return None

    def list_close_certification_runs(
        self,
        *,
        opportunity_id: str | None = None,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> list[CloseCertificationRunV1]:
        if opportunity_id not in (None, ""):
            roots = [
                self.close_certification_run_dir(
                    opportunity_id=str(opportunity_id),
                    crm_org_id=crm_org_id,
                    org_alias=org_alias,
                )
            ]
        else:
            root = self.root / "close_runs"
            if crm_org_id not in (None, "") or org_alias not in (None, ""):
                org_root = root / _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias)
                roots = [path for path in sorted(org_root.iterdir()) if path.is_dir()] if org_root.exists() else []
            else:
                roots = []
                if root.exists():
                    for org_root in sorted(root.iterdir()):
                        if not org_root.is_dir():
                            continue
                        roots.extend(path for path in sorted(org_root.iterdir()) if path.is_dir())
        runs: list[CloseCertificationRunV1] = []
        for current_root in roots:
            if not current_root.exists():
                continue
            for path in sorted(current_root.glob("*.json")):
                try:
                    runs.append(CloseCertificationRunV1.from_dict(_read_json(path)))
                except Exception:
                    continue
        return runs

    def load_close_certification_run(
        self,
        *,
        run_id: str,
        opportunity_id: str | None = None,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> CloseCertificationRunV1 | None:
        normalized_run_id = str(run_id or "").strip()
        if not normalized_run_id:
            return None
        if opportunity_id not in (None, ""):
            path = self.close_certification_run_path(
                opportunity_id=str(opportunity_id),
                run_id=normalized_run_id,
                crm_org_id=crm_org_id,
                org_alias=org_alias,
            )
            if path.exists():
                return CloseCertificationRunV1.from_dict(_read_json(path))
        for item in self.list_close_certification_runs(
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        ):
            if item.run_id == normalized_run_id:
                return item
        return None

    def load_reconciliation_packet(
        self,
        *,
        opportunity_id: str,
        packet_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> ReconciliationPacketV1 | None:
        normalized_packet_id = str(packet_id or "").strip()
        if not normalized_packet_id:
            return None
        path = self.reconciliation_packet_path(
            opportunity_id=opportunity_id,
            packet_id=normalized_packet_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        )
        if not path.exists():
            return None
        return ReconciliationPacketV1.from_dict(_read_json(path))

    def load_latest_reconciliation_packet(
        self,
        *,
        opportunity_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> ReconciliationPacketV1 | None:
        root = self.reconciliation_packet_dir(
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        )
        if not root.exists():
            return None
        latest_path = None
        latest_ts = None
        for path in sorted(root.glob("*.json")):
            try:
                payload = _read_json(path)
                generated_at = str(payload.get("generated_at") or "")
            except Exception:
                continue
            if latest_path is None or generated_at > str(latest_ts or ""):
                latest_path = path
                latest_ts = generated_at
        if latest_path is None:
            return None
        return ReconciliationPacketV1.from_dict(_read_json(latest_path))

    def list_quote_document_fingerprints(
        self,
        *,
        opportunity_id: str | None = None,
        quote_id: str | None = None,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> list[QuoteDocumentFingerprintV1]:
        roots: list[Path] = []
        if opportunity_id not in (None, ""):
            if quote_id not in (None, ""):
                roots = [
                    self.quote_document_fingerprint_dir(
                        opportunity_id=str(opportunity_id),
                        quote_id=str(quote_id),
                        crm_org_id=crm_org_id,
                        org_alias=org_alias,
                    )
                ]
            else:
                opportunity_root = self.root / "quote_fingerprints" / _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias) / _safe_key(opportunity_id, default="unknown-opportunity")
                roots = [path for path in sorted(opportunity_root.iterdir()) if path.is_dir()] if opportunity_root.exists() else []
        elif quote_id not in (None, ""):
            root = self.root / "quote_fingerprints" / _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias)
            if root.exists():
                for opportunity_root in sorted(root.iterdir()):
                    if not opportunity_root.is_dir():
                        continue
                    quote_root = opportunity_root / _safe_key(quote_id, default="unknown-quote")
                    if quote_root.exists():
                        roots.append(quote_root)
        else:
            root = self.root / "quote_fingerprints" / _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias)
            if root.exists():
                for opportunity_root in sorted(root.iterdir()):
                    if not opportunity_root.is_dir():
                        continue
                    roots.extend(path for path in sorted(opportunity_root.iterdir()) if path.is_dir())
        fingerprints: list[QuoteDocumentFingerprintV1] = []
        for root in roots:
            if not root.exists():
                continue
            for path in sorted(root.glob("*.json")):
                try:
                    fingerprints.append(QuoteDocumentFingerprintV1.from_dict(_read_json(path)))
                except Exception:
                    continue
        return fingerprints

    def save_generated_config(
        self,
        config: DealDeskConfig,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        path = self.generated_config_path(crm_org_id=crm_org_id, org_alias=org_alias)
        return _write_config_payload(path, config)

    def load_generated_config(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> DealDeskConfig | None:
        yaml_path = self.generated_config_path(crm_org_id=crm_org_id, org_alias=org_alias)
        if yaml_path.exists() and yaml is not None:
            with yaml_path.open(encoding="utf-8") as handle:
                payload = yaml.safe_load(handle) or {}
            if isinstance(payload, dict):
                return DealDeskConfig.model_validate(payload)
        json_path = yaml_path.with_suffix(".json")
        if json_path.exists():
            return DealDeskConfig.model_validate(_read_json(json_path))
        return None

    def load_effective_config(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
        default_loader: Callable[[], DealDeskConfig] | None = None,
    ) -> DealDeskConfig:
        generated = self.load_generated_config(crm_org_id=crm_org_id, org_alias=org_alias)
        if generated is not None:
            return generated
        loader = default_loader or load_dealdesk_config
        return loader()

    def load_effective_config_info(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> tuple[DealDeskConfig, str, str]:
        generated = self.load_generated_config(crm_org_id=crm_org_id, org_alias=org_alias)
        if generated is not None:
            return generated, "generated", str(self._existing_generated_config_path(crm_org_id=crm_org_id, org_alias=org_alias))
        return load_dealdesk_config(), "default", str(DEFAULT_CONFIG_PATH)

    def save_config_mutation_receipt(
        self,
        receipt: Any,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        receipt_id = _safe_key(getattr(receipt, "receipt_id", None), default="receipt")
        path = self.config_mutation_receipt_path(
            receipt_id=receipt_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        )
        payload = receipt.to_dict() if hasattr(receipt, "to_dict") else dict(receipt)
        return _write_json(path, payload)

    def load_config_mutation_receipt(
        self,
        *,
        receipt_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Any | None:
        normalized_receipt_id = str(receipt_id or "").strip()
        if not normalized_receipt_id:
            return None
        path = self.config_mutation_receipt_path(
            receipt_id=normalized_receipt_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        )
        if not path.exists():
            return None
        from .mutations import DealDeskConfigMutationReceiptV1

        return DealDeskConfigMutationReceiptV1.model_validate(_read_json(path))

    def list_config_mutation_receipts(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> list[Any]:
        root = self.config_mutation_receipt_dir(crm_org_id=crm_org_id, org_alias=org_alias)
        if not root.exists():
            return []
        from .mutations import DealDeskConfigMutationReceiptV1

        receipts: list[Any] = []
        for path in sorted(root.glob("*.json")):
            try:
                receipts.append(DealDeskConfigMutationReceiptV1.model_validate(_read_json(path)))
            except Exception:
                continue
        return receipts

    def find_latest_config_mutation_receipt(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
        action: str | None = None,
        trigger_key: str | None = None,
    ) -> Any | None:
        normalized_action = str(action or "").strip().lower()
        normalized_trigger_key = str(trigger_key or "").strip().lower()
        receipts = sorted(
            self.list_config_mutation_receipts(crm_org_id=crm_org_id, org_alias=org_alias),
            key=lambda item: str(getattr(item, "created_at", "") or ""),
            reverse=True,
        )
        for item in receipts:
            if normalized_action and str(getattr(item, "action", "") or "").strip().lower() != normalized_action:
                continue
            if normalized_trigger_key and str(getattr(item, "trigger_key", "") or "").strip().lower() != normalized_trigger_key:
                continue
            return item
        return None

    def save_capability_refresh_receipt(
        self,
        receipt: Any,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        receipt_id = _safe_key(getattr(receipt, "receipt_id", None), default="receipt")
        path = self.capability_refresh_receipt_path(
            receipt_id=receipt_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        )
        payload = receipt.to_dict() if hasattr(receipt, "to_dict") else dict(receipt)
        return _write_json(path, payload)

    def load_capability_refresh_receipt(
        self,
        *,
        receipt_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Any | None:
        normalized_receipt_id = str(receipt_id or "").strip()
        if not normalized_receipt_id:
            return None
        path = self.capability_refresh_receipt_path(
            receipt_id=normalized_receipt_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        )
        if not path.exists():
            return None
        from .capability_refresh import DealDeskCapabilityRefreshReceiptV1

        return DealDeskCapabilityRefreshReceiptV1.model_validate(_read_json(path))

    def list_capability_refresh_receipts(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> list[Any]:
        root = self.capability_refresh_receipt_dir(crm_org_id=crm_org_id, org_alias=org_alias)
        if not root.exists():
            return []
        from .capability_refresh import DealDeskCapabilityRefreshReceiptV1

        receipts: list[Any] = []
        for path in sorted(root.glob("*.json")):
            try:
                receipts.append(DealDeskCapabilityRefreshReceiptV1.model_validate(_read_json(path)))
            except Exception:
                continue
        return receipts

    def find_latest_capability_refresh_receipt(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Any | None:
        receipts = sorted(
            self.list_capability_refresh_receipts(crm_org_id=crm_org_id, org_alias=org_alias),
            key=lambda item: str(getattr(item, "created_at", "") or ""),
            reverse=True,
        )
        return receipts[0] if receipts else None

    def save_capability_refresh_draft(
        self,
        config: DealDeskConfig,
        *,
        receipt_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        path = self.capability_refresh_draft_path(
            receipt_id=receipt_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        )
        return _write_config_payload(path, config)

    def load_capability_refresh_draft(
        self,
        *,
        draft_path: str | Path,
    ) -> DealDeskConfig | None:
        path = Path(draft_path)
        if not path.exists() and path.suffix.lower() in {".yaml", ".yml"}:
            json_path = path.with_suffix(".json")
            if json_path.exists():
                path = json_path
        return _read_config_payload(path)

    def save_capability_draft_promotion_receipt(
        self,
        receipt: Any,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        receipt_id = _safe_key(getattr(receipt, "receipt_id", None), default="receipt")
        path = self.capability_draft_promotion_receipt_path(
            receipt_id=receipt_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        )
        payload = receipt.to_dict() if hasattr(receipt, "to_dict") else dict(receipt)
        return _write_json(path, payload)

    def load_capability_draft_promotion_receipt(
        self,
        *,
        receipt_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Any | None:
        normalized_receipt_id = str(receipt_id or "").strip()
        if not normalized_receipt_id:
            return None
        path = self.capability_draft_promotion_receipt_path(
            receipt_id=normalized_receipt_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        )
        if not path.exists():
            return None
        from .capability_promotion import DealDeskCapabilityDraftPromotionReceiptV1

        return DealDeskCapabilityDraftPromotionReceiptV1.model_validate(_read_json(path))

    def list_capability_draft_promotion_receipts(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> list[Any]:
        root = self.capability_draft_promotion_receipt_dir(crm_org_id=crm_org_id, org_alias=org_alias)
        if not root.exists():
            return []
        from .capability_promotion import DealDeskCapabilityDraftPromotionReceiptV1

        receipts: list[Any] = []
        for path in sorted(root.glob("*.json")):
            try:
                receipts.append(DealDeskCapabilityDraftPromotionReceiptV1.model_validate(_read_json(path)))
            except Exception:
                continue
        return receipts

    def find_latest_capability_draft_promotion_receipt(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
        source_refresh_receipt_id: str | None = None,
    ) -> Any | None:
        normalized_refresh_receipt_id = str(source_refresh_receipt_id or "").strip().lower()
        receipts = sorted(
            self.list_capability_draft_promotion_receipts(crm_org_id=crm_org_id, org_alias=org_alias),
            key=lambda item: str(getattr(item, "created_at", "") or ""),
            reverse=True,
        )
        for item in receipts:
            if normalized_refresh_receipt_id and (
                str(getattr(item, "source_refresh_receipt_id", "") or "").strip().lower() != normalized_refresh_receipt_id
            ):
                continue
            return item
        return None

    def save_quote_draft_plan(
        self,
        plan: QuoteDraftPlanV1,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        path = self.quote_draft_plan_path(
            opportunity_id=plan.opportunity_id,
            crm_org_id=crm_org_id or plan.crm_org_id,
            org_alias=org_alias,
        )
        return _write_json(path, plan.to_dict())

    def load_quote_draft_plan(
        self,
        *,
        opportunity_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> QuoteDraftPlanV1 | None:
        path = self.quote_draft_plan_path(
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        )
        if not path.exists():
            return None
        return QuoteDraftPlanV1.model_validate(_read_json(path))

    def generated_config_path(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        org_key = _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias)
        return self.root / "configs" / org_key / "dealdesk.generated.yaml"

    def config_mutation_receipt_dir(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        org_key = _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias)
        return self.root / "config_receipts" / org_key

    def config_mutation_receipt_path(
        self,
        *,
        receipt_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        receipt_key = _safe_key(receipt_id, default="receipt")
        return self.config_mutation_receipt_dir(
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        ) / f"{receipt_key}.json"

    def capability_refresh_receipt_dir(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        org_key = _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias)
        return self.root / "capability_refresh_receipts" / org_key

    def capability_refresh_receipt_path(
        self,
        *,
        receipt_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        receipt_key = _safe_key(receipt_id, default="receipt")
        return self.capability_refresh_receipt_dir(
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        ) / f"{receipt_key}.json"

    def capability_refresh_draft_dir(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        org_key = _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias)
        return self.root / "capability_refresh_drafts" / org_key

    def capability_refresh_draft_path(
        self,
        *,
        receipt_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        draft_key = _safe_key(receipt_id, default="draft")
        return self.capability_refresh_draft_dir(
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        ) / f"{draft_key}.yaml"

    def capability_draft_promotion_receipt_dir(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        org_key = _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias)
        return self.root / "capability_draft_promotion_receipts" / org_key

    def capability_draft_promotion_receipt_path(
        self,
        *,
        receipt_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        receipt_key = _safe_key(receipt_id, default="receipt")
        return self.capability_draft_promotion_receipt_dir(
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        ) / f"{receipt_key}.json"

    def quote_environment_profile_path(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        return self._quote_environment_path(crm_org_id=crm_org_id, org_alias=org_alias)

    def deal_pattern_profile_path(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        return self._deal_pattern_path(crm_org_id=crm_org_id, org_alias=org_alias)

    def context_path(
        self,
        *,
        opportunity_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        return self._context_path(
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            opportunity_id=opportunity_id,
        )

    def quote_draft_plan_path(
        self,
        *,
        opportunity_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        org_key = _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias)
        opp_key = _safe_key(opportunity_id, default="unknown-opportunity")
        return self.root / "plans" / "quote_draft" / org_key / f"{opp_key}.json"

    def reconciliation_packet_dir(
        self,
        *,
        opportunity_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        org_key = _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias)
        opp_key = _safe_key(opportunity_id, default="unknown-opportunity")
        return self.root / "reconciliation" / org_key / opp_key

    def reconciliation_packet_path(
        self,
        *,
        opportunity_id: str,
        packet_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        packet_key = _safe_key(packet_id, default="packet")
        return self.reconciliation_packet_dir(
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        ) / f"{packet_key}.json"

    def quote_document_fingerprint_dir(
        self,
        *,
        opportunity_id: str,
        quote_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        org_key = _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias)
        opp_key = _safe_key(opportunity_id, default="unknown-opportunity")
        quote_key = _safe_key(quote_id, default="unknown-quote")
        return self.root / "quote_fingerprints" / org_key / opp_key / quote_key

    def quote_document_fingerprint_path(
        self,
        *,
        opportunity_id: str,
        quote_id: str,
        fingerprint_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        fingerprint_key = _safe_key(fingerprint_id, default="quote-fingerprint")
        return self.quote_document_fingerprint_dir(
            opportunity_id=opportunity_id,
            quote_id=quote_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        ) / f"{fingerprint_key}.json"

    def close_certification_run_dir(
        self,
        *,
        opportunity_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        org_key = _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias)
        opp_key = _safe_key(opportunity_id, default="unknown-opportunity")
        return self.root / "close_runs" / org_key / opp_key

    def close_certification_run_path(
        self,
        *,
        opportunity_id: str,
        run_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        run_key = _safe_key(run_id, default="close-run")
        return self.close_certification_run_dir(
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        ) / f"{run_key}.json"

    def post_close_trigger_run_dir(
        self,
        *,
        opportunity_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        org_key = _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias)
        opp_key = _safe_key(opportunity_id, default="unknown-opportunity")
        return self.root / "post_close" / org_key / opp_key

    def post_close_trigger_run_path(
        self,
        *,
        opportunity_id: str,
        run_id: str,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        run_key = _safe_key(run_id, default="trigger-run")
        return self.post_close_trigger_run_dir(
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        ) / f"{run_key}.json"

    def _quote_environment_path(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        org_key = _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias)
        return self.root / "profiles" / "quote_environment" / f"{org_key}.json"

    def _deal_pattern_path(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        org_key = _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias)
        return self.root / "profiles" / "deal_pattern" / f"{org_key}.json"

    def _context_path(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
        opportunity_id: str,
    ) -> Path:
        org_key = _org_storage_key(crm_org_id=crm_org_id, org_alias=org_alias)
        opp_key = _safe_key(opportunity_id, default="unknown-opportunity")
        return self.root / "contexts" / org_key / f"{opp_key}.json"

    def _existing_generated_config_path(
        self,
        *,
        crm_org_id: str | None = None,
        org_alias: str | None = None,
    ) -> Path:
        yaml_path = self.generated_config_path(crm_org_id=crm_org_id, org_alias=org_alias)
        if yaml_path.exists():
            return yaml_path
        json_path = yaml_path.with_suffix(".json")
        if json_path.exists():
            return json_path
        return yaml_path


__all__ = ["DealDeskStore", "resolve_dealdesk_state_dir"]
