"""Persistence and workflow helpers for seller quote revisions."""

from __future__ import annotations

import json
from pathlib import Path
from typing import Any

from .eventing import resolve_crm_org_id, utc_now_iso
from .quote_intent import QuoteIntentV1
from .store import DealDeskStore
from .workflow import (
    QuoteWorkflowHandoffState,
    QuoteWorkflowRunV1,
    SlackResponseTargetV1,
    build_quote_workflow_run_id,
    persist_quote_workflow_run,
    record_quote_workflow_transition,
)


def quote_revision_approval_context_path(*, state_dir: str | None, run_id: str) -> Path:
    base_dir = Path(state_dir) if state_dir else DealDeskStore().state_dir
    run_key = str(run_id or "").strip() or "seller-quote-revision"
    return Path(base_dir) / "pending" / run_key / "dealdesk_quote_change_context.json"


def save_quote_revision_approval_context_payload(
    *,
    run_id: str,
    state_dir: str | None,
    payload: dict[str, Any],
) -> Path:
    path = quote_revision_approval_context_path(state_dir=state_dir, run_id=run_id)
    path.parent.mkdir(parents=True, exist_ok=True)
    temp_path = path.with_suffix(".json.tmp")
    temp_path.write_text(
        json.dumps(payload, indent=2, sort_keys=True),
        encoding="utf-8",
    )
    temp_path.replace(path)
    return path


def load_quote_revision_approval_context_payload(
    *,
    run_id: str,
    state_dir: str | None,
) -> dict[str, Any] | None:
    path = quote_revision_approval_context_path(state_dir=state_dir, run_id=run_id)
    if not path.exists():
        return None
    try:
        payload = json.loads(path.read_text(encoding="utf-8"))
    except Exception:
        return None
    return payload if isinstance(payload, dict) else None


def build_seller_quote_revision_workflow_run(
    *,
    store: DealDeskStore,
    intent: QuoteIntentV1,
    seller_slack_target: SlackResponseTargetV1 | None = None,
) -> QuoteWorkflowRunV1:
    crm_org_id = resolve_crm_org_id(org_alias=intent.org_alias, crm_org_id=intent.crm_org_id)
    observed_at = utc_now_iso()
    return QuoteWorkflowRunV1(
        run_id=build_quote_workflow_run_id(
            opportunity_id=intent.opportunity_id,
            prefix="dealdesk_seller_quote_change",
        ),
        opportunity_id=intent.opportunity_id,
        crm_org_id=crm_org_id,
        org_alias=intent.org_alias,
        workflow_kind="seller_quote_revision",
        entrypoint="seller_quote_revision",
        state_dir=str(store.state_dir),
        triggered_at=observed_at,
        last_transition_at=observed_at,
        current_state="intake_received",
        intent=intent.to_dict(),
        pdf_status="not_requested",
        seller_slack_target=seller_slack_target,
    )


def persist_seller_quote_revision_preview_snapshot(
    *,
    store: DealDeskStore,
    run: QuoteWorkflowRunV1,
    preview_payload: dict[str, Any],
    context_id: str | None,
    detected_engine: str | None,
    current_quote_id: str | None,
    current_quote_status: str | None,
) -> None:
    run.context_id = context_id or run.context_id
    run.detected_engine = detected_engine
    run.preview = dict(preview_payload)
    run.current_quote_id = str(current_quote_id or "").strip() or run.current_quote_id
    persist_quote_workflow_run(
        store,
        run,
        engine=detected_engine,
        quote_status=current_quote_status,
    )


def prepare_seller_quote_revision_handoff_run(
    *,
    store: DealDeskStore,
    preview: Any,
    seller_slack_target: SlackResponseTargetV1 | dict[str, Any] | None = None,
    seller_actor_id: str | None = None,
    source_channel: str | None = None,
) -> QuoteWorkflowRunV1:
    resolved_seller_slack_target = (
        SlackResponseTargetV1.model_validate(seller_slack_target)
        if seller_slack_target is not None
        else None
    )
    run = build_seller_quote_revision_workflow_run(
        store=store,
        intent=preview.intent,
        seller_slack_target=resolved_seller_slack_target,
    )
    run.handoff_state = "queued"
    run.handoff_updated_at = run.triggered_at
    run.handoff_seller_actor_id = str(seller_actor_id or "").strip() or None
    run.handoff_source_channel = str(source_channel or "").strip() or None
    record_quote_workflow_transition(
        store,
        run,
        to_state="intake_received",
        observed_at=run.triggered_at,
        reason="seller_quote_revision_handoff_started",
    )
    record_quote_workflow_transition(
        store,
        run,
        to_state="readiness_check",
        observed_at=utc_now_iso(),
        reason="seller_quote_revision_handoff_preview_started",
    )
    persist_seller_quote_revision_preview_snapshot(
        store=store,
        run=run,
        preview_payload=preview.to_dict(),
        context_id=getattr(preview, "context_id", None),
        detected_engine=getattr(preview, "detected_engine", None),
        current_quote_id=(
            str(getattr(getattr(preview, "selected_quote", None), "quote_id", "") or "").strip() or None
        ),
        current_quote_status=(
            str(getattr(getattr(preview, "selected_quote", None), "status", "") or "").strip() or None
        ),
    )
    return run


def finalize_seller_quote_revision_handoff_run(
    *,
    store: DealDeskStore,
    run: QuoteWorkflowRunV1,
    preview: Any,
    routing_result: dict[str, Any] | None = None,
    note: str | None = None,
) -> None:
    normalized_note = str(note or "").strip()
    run.receipt_outcome = "handed_off"
    run.approval_required = False
    run.pending_run_id = None
    run.pending_plan_path = None
    run.latest_result = {
        "receipt_outcome": "handed_off",
        "status": str(getattr(preview, "status", "") or "").strip(),
        "preview_policy_state": str(getattr(preview, "preview_policy_state", "") or "").strip(),
        "apply_supported": bool(getattr(preview, "apply_supported", False)),
        "support_reason": str(getattr(preview, "support_reason", "") or "").strip(),
        "apply_support_reason": str(getattr(preview, "apply_support_reason", "") or "").strip(),
        "next_step": str(getattr(preview, "next_step", "") or "").strip(),
        "routing": dict(routing_result or {}),
    }
    run.handoff_state = run.handoff_state or "queued"
    run.handoff_updated_at = utc_now_iso()
    if normalized_note:
        run.notes.append(normalized_note)
        run.handoff_note = normalized_note
    persist_quote_workflow_run(
        store,
        run,
        engine=run.detected_engine,
        quote_status=(
            str(getattr(getattr(preview, "selected_quote", None), "status", "") or "").strip() or None
        ),
    )
    record_quote_workflow_transition(
        store,
        run,
        to_state="delivered",
        observed_at=utc_now_iso(),
        reason="seller_quote_revision_handed_off_to_revops",
        engine=run.detected_engine,
        quote_status=(
            str(getattr(getattr(preview, "selected_quote", None), "status", "") or "").strip() or None
        ),
    )


def update_seller_quote_revision_handoff_state(
    *,
    store: DealDeskStore,
    run: QuoteWorkflowRunV1,
    handoff_state: QuoteWorkflowHandoffState,
    actor_id: str | None = None,
    note: str | None = None,
) -> None:
    observed_at = utc_now_iso()
    normalized_actor = str(actor_id or "").strip() or None
    normalized_note = str(note or "").strip() or None
    run.handoff_state = handoff_state
    run.handoff_actor_id = normalized_actor or run.handoff_actor_id
    run.handoff_updated_at = observed_at
    if normalized_note:
        run.handoff_note = normalized_note
        run.notes.append(normalized_note)
    latest_result = dict(run.latest_result or {})
    latest_result.update(
        {
            "receipt_outcome": str(run.receipt_outcome or "").strip() or "handed_off",
            "handoff_state": handoff_state,
            "handoff_actor_id": run.handoff_actor_id,
            "handoff_updated_at": observed_at,
            "handoff_note": normalized_note,
        }
    )
    run.latest_result = latest_result
    preview_payload = dict(run.preview or {})
    selected_quote_payload = (
        dict(preview_payload.get("selected_quote"))
        if isinstance(preview_payload.get("selected_quote"), dict)
        else {}
    )
    persist_quote_workflow_run(
        store,
        run,
        engine=run.detected_engine,
        quote_status=str(selected_quote_payload.get("status") or "").strip() or None,
    )


def quote_status_from_summary(summary: Any) -> str | None:
    selected_quote = getattr(summary, "selected_quote", None)
    if selected_quote is None:
        return None
    return str(getattr(selected_quote, "status", "") or "").strip() or None


def plan_snapshot(plan: Any) -> dict[str, Any]:
    if hasattr(plan, "to_dict"):
        payload = plan.to_dict()
        return payload if isinstance(payload, dict) else {}
    return {
        "run_id": str(getattr(plan, "run_id", "") or "").strip(),
        "approvals_required": bool(getattr(plan, "approvals_required", False)),
        "policy_hash": str(getattr(plan, "policy_hash", "") or "").strip() or None,
    }


def update_seller_quote_revision_workflow_result(
    *,
    store: DealDeskStore,
    run: QuoteWorkflowRunV1,
    result_payload: dict[str, Any],
    receipt_outcome: str | None,
    receipt_dir: str | None,
    approval_required: bool,
    updated_quote_status: Any,
    pending_run_id: str | None = None,
    pending_plan_path: str | None = None,
) -> None:
    run.receipt_outcome = str(receipt_outcome or "").strip() or None
    run.receipt_dir = str(receipt_dir or "").strip() or None
    run.pending_run_id = str(pending_run_id or "").strip() or None
    run.pending_plan_path = str(pending_plan_path or "").strip() or None
    run.approval_required = bool(approval_required)
    run.apply_result = dict(result_payload)
    run.latest_result = dict(result_payload)
    persist_quote_workflow_run(
        store,
        run,
        engine=run.detected_engine,
        quote_status=quote_status_from_summary(updated_quote_status),
    )
