"""Post-execution helpers for seller quote revisions."""

from __future__ import annotations

from pathlib import Path
from typing import Any, Callable

from .eventing import build_pattern_update_event, save_pattern_update_events, utc_now_iso
from .store import DealDeskStore


def save_quote_revision_event(
    *,
    store: DealDeskStore,
    preview: Any,
    intent: Any,
    source_receipt_id: str,
    receipt_dir: Path,
) -> None:
    if preview.selected_quote is None or (
        preview.field_preview is None and preview.line_item_preview is None
    ):
        return
    context = store.load_context(
        opportunity_id=preview.opportunity_id,
        crm_org_id=preview.crm_org_id,
        org_alias=preview.org_alias,
    )
    raw_record: dict[str, Any] = {
        "Id": preview.selected_quote.quote_id,
        "OpportunityId": preview.opportunity_id,
        "Status": preview.selected_quote.status,
    }
    custom: dict[str, Any] = {
        "engine": preview.detected_engine,
        "quote_id": preview.selected_quote.quote_id,
        "semantic_key": intent.semantic_key,
        "preview_policy_state": preview.preview_policy_state,
    }
    evidence_ids = [
        preview.opportunity_id,
        preview.selected_quote.quote_id,
        source_receipt_id,
        *[item.label for item in preview.evidence[:2]],
    ]
    if preview.field_preview is not None:
        raw_record[preview.field_preview.field_name] = preview.field_preview.proposed_value
        custom.update(
            {
                "header_only": True,
                "field_name": preview.field_preview.field_name,
            }
        )
    elif preview.line_item_preview is not None:
        line_preview = preview.line_item_preview
        line_model = line_preview.proposed_line or (
            line_preview.current_lines[0] if line_preview.current_lines else None
        )
        custom.update(
            {
                "header_only": False,
                "line_item": True,
                "operation": line_preview.operation,
                "line_object_name": line_preview.line_object_name,
                "product_reference_type": line_preview.product_reference_type,
                "product_reference_value": line_preview.product_reference_value,
            }
        )
        if line_model is not None:
            if line_model.line_item_id:
                raw_record["QuoteLineItemId"] = line_model.line_item_id
                evidence_ids.append(line_model.line_item_id)
            if line_model.product_id:
                raw_record["Product2Id"] = line_model.product_id
            if line_model.product_code:
                raw_record["ProductCode"] = line_model.product_code
                evidence_ids.append(line_model.product_code)
            raw_record["ProductName"] = line_model.product_name
            if line_model.pricebook_entry_id:
                raw_record["PricebookEntryId"] = line_model.pricebook_entry_id
            if line_model.quantity is not None:
                raw_record["Quantity"] = line_model.quantity
        raw_record["LineItemOperation"] = line_preview.operation
    event = build_pattern_update_event(
        source_type="quote_receipt",
        crm_org_id=preview.crm_org_id,
        opportunity_id=preview.opportunity_id,
        source_ref=str((receipt_dir / "receipt.json").resolve()),
        observed_at=utc_now_iso(),
        source_receipt_id=source_receipt_id,
        raw_record=raw_record,
        extracted_motion_id=context.inferred_motion_id if context is not None else None,
        confidence=1.0,
        discount_pct=intent.requested_discount_pct,
        term_months=intent.requested_term_months,
        payment_terms=intent.requested_payment_terms,
        outcome="updated",
        custom=custom,
        evidence_ids=evidence_ids,
    )
    save_pattern_update_events(
        store=store,
        events=[event],
        org_alias=preview.org_alias,
        refresh_profile=True,
    )


def refresh_quote_status_after_revision(
    *,
    preview: Any,
    store: DealDeskStore,
    receipt_outcome: str,
    status_from_context: Callable[..., Any],
    load_status_summary: Callable[..., Any],
    dedupe_strings: Callable[[list[str]], list[str]],
    evidence_factory: Callable[..., Any],
    status_factory: Callable[..., Any],
) -> Any:
    try:
        context = store.load_context(
            opportunity_id=preview.opportunity_id,
            crm_org_id=preview.crm_org_id,
            org_alias=preview.org_alias,
        )
        environment_profile = store.load_quote_environment_profile(
            crm_org_id=preview.crm_org_id,
            org_alias=preview.org_alias,
        )
        if context is not None and environment_profile is not None:
            return status_from_context(
                opportunity_id=preview.opportunity_id,
                crm_org_id=preview.crm_org_id,
                org_alias=preview.org_alias,
                readiness_mode=preview.readiness_mode,
                context=context,
                environment_profile=environment_profile,
                store=store,
            )
        return load_status_summary(
            opportunity_id=preview.opportunity_id,
            org_alias=preview.org_alias,
            state_dir=str(store.state_dir),
            force_refresh=True,
        )
    except Exception as exc:
        refresh_error = str(exc) or "Unable to refresh seller-facing quote status after guided revision."
        context = store.load_context(
            opportunity_id=preview.opportunity_id,
            crm_org_id=preview.crm_org_id,
            org_alias=preview.org_alias,
        )
        context_id = preview.context_id or (context.context_id if context is not None else None)
        lifecycle_state = (
            str(context.lifecycle_state or "").strip() if context is not None else ""
        ) or "unknown"
        close_workflow_state = (
            str(context.close_workflow_state or "").strip() if context is not None else ""
        ) or "unknown"
        if receipt_outcome == "already_set":
            support_reason = (
                "Requested quote revision was already present, but refreshed seller quote status is not available yet."
            )
            evidence_detail = (
                "Gremlin skipped the quote revision because the requested value was already set, "
                f"but could not refresh seller-facing quote status: {refresh_error}"
            )
            next_step = (
                "Refresh quote status in Slack or use the native quote tool to confirm the current "
                "quote state before relying on seller-facing status here."
            )
        elif receipt_outcome == "approval_required":
            support_reason = (
                "Quote revision is queued for approval, but refreshed seller quote status is not available yet."
            )
            evidence_detail = (
                "Gremlin staged the quote revision for approval, but could not refresh seller-facing "
                f"quote status: {refresh_error}"
            )
            next_step = (
                "Approval is still required for this quote change. Refresh quote status in Slack or "
                "use the native quote tool until RevOps confirms the quote-status surface for this org."
            )
        else:
            support_reason = (
                "Quote revision completed, but refreshed seller quote status is not available yet."
            )
            evidence_detail = (
                "Gremlin applied the quote revision, but could not refresh seller-facing quote status: "
                f"{refresh_error}"
            )
            next_step = (
                "Refresh quote status in Slack or use the native quote tool to confirm the current "
                "quote state until RevOps confirms the quote-status surface for this org."
            )
        capability_gaps = dedupe_strings(
            [
                *list(preview.capability_gaps or []),
                "Seller-facing quote status refresh is unavailable because Gremlin could not verify the current quote after this revision.",
                refresh_error,
            ]
        )
        evidence = list(preview.evidence or [])
        evidence.append(
            evidence_factory(
                source_type="quote_status_refresh",
                label="Quote Status Refresh",
                detail=evidence_detail,
            )
        )
        return status_factory(
            opportunity_id=preview.opportunity_id,
            crm_org_id=preview.crm_org_id,
            org_alias=preview.org_alias,
            context_id=context_id,
            lifecycle_state=lifecycle_state,
            close_workflow_state=close_workflow_state,
            readiness_mode=preview.readiness_mode,
            detected_engine=preview.detected_engine,
            status="partial",
            support_reason=support_reason,
            capability_gaps=capability_gaps,
            quote_count=1 if preview.selected_quote is not None else 0,
            selected_quote=preview.selected_quote,
            approval_state="unavailable",
            matched_approval_route_names=list(preview.matched_approval_route_names or []),
            evidence=evidence,
            next_step=next_step,
        )


def build_quote_revision_apply_result_payload(
    *,
    intent: Any,
    preview: Any,
    receipt_outcome: str,
    updated_quote_status: Any,
    receipt_run_id: str | None = None,
    receipt_dir: str | None = None,
    pending_run_id: str | None = None,
    pending_plan_path: str | None = None,
    already_set: bool = False,
) -> dict[str, Any]:
    return {
        "opportunity_id": intent.opportunity_id,
        "crm_org_id": intent.crm_org_id,
        "org_alias": intent.org_alias,
        "context_id": preview.context_id,
        "intent": intent,
        "field_preview": preview.field_preview,
        "line_item_preview": preview.line_item_preview,
        "preview_policy_state": preview.preview_policy_state,
        "receipt_run_id": receipt_run_id,
        "receipt_dir": receipt_dir,
        "receipt_outcome": receipt_outcome,
        "applied": receipt_outcome == "success",
        "already_set": bool(already_set),
        "approval_required": receipt_outcome == "approval_required",
        "pending_run_id": pending_run_id,
        "pending_plan_path": pending_plan_path,
        "updated_quote_status": updated_quote_status,
    }
