<script lang="ts">
  import { createEventDispatcher } from "svelte";
  import { clientFetch } from "$lib/client-fetch";
  import type { SalesOpportunity } from "$lib/optima-api/modules/sales";
  import type {
    WorkflowStatusResponse,
    WorkflowAvailableAction,
    WorkflowAction,
    WorkflowActionPayload,
    WorkflowResult,
  } from "$lib/optima-api/modules/sales";
  import {
    WORKFLOW_STATUS_LABELS,
    STATUS_ID_TO_KEY,
    TERMINAL_STATUSES,
    REOPENABLE_STATUSES,
    QUOTE_CONFIRMED_STATUSES,
    ADD_TIME_EXCLUDED_STATUSES,
  } from "$lib/optima-api/modules/sales";
  import type { PermissionMap } from "$lib/permissions";
  import type {
    CommittedQuote,
    OpportunityActivity,
  } from "$lib/optima-api/modules/sales";
  import WorkflowActionModal from "./WorkflowActionModal.svelte";
  import SendQuoteModal from "./SendQuoteModal.svelte";
  import ReviewDecisionModal from "./ReviewDecisionModal.svelte";
  import FinalizeModal from "./FinalizeModal.svelte";
  import AddTimeModal from "./AddTimeModal.svelte";
  import CreateScheduleEntryModal from "./CreateScheduleEntryModal.svelte";
  import { formatDateTime } from "../types";

  const dispatch = createEventDispatcher<{
    workflowChanged: { result: WorkflowResult; freshWorkflowStatus: WorkflowStatusResponse | null };
  }>();

  export let opportunity: SalesOpportunity | null;
  export let workflowStatus: WorkflowStatusResponse | null;
  export let permissions: PermissionMap;
  export let opportunityId: string;
  export let inline: boolean = false;
  export let quotes: CommittedQuote[] = [];
  export let activities: OpportunityActivity[] = [];

  // Workflow state
  let activeModal: WorkflowAction | null = null;
  let workflowError: string | null = null;
  let isSubmitting = false;
  let preselectedOutcome: "won" | "lost" | null = null;

  // Add Time modal state
  let showAddTimeModal = false;
  let addTimeActivities: Array<{ cwActivityId: number; name: string; optimaType: string | null }> = [];
  let isLoadingActivities = false;

  // Create Schedule Entry modal state
  let showScheduleEntryModal = false;
  let scheduleEntryError: string | null = null;
  let isScheduleEntrySubmitting = false;

  // Derived state
  $: statusKey = workflowStatus
    ? (STATUS_ID_TO_KEY[workflowStatus.currentStatusId] ?? null)
    : null;
  $: statusLabel = statusKey
    ? WORKFLOW_STATUS_LABELS[statusKey]
    : (workflowStatus?.currentStatus ?? opportunity?.status?.name ?? "Unknown");
  $: isTerminal = statusKey ? TERMINAL_STATUSES.has(statusKey) : false;
  $: isReopenable = statusKey ? REOPENABLE_STATUSES.has(statusKey) : false;
  $: quoteConfirmed = statusKey
    ? QUOTE_CONFIRMED_STATUSES.has(statusKey)
    : false;
  $: isOptimaStage = workflowStatus?.isOptimaStage ?? false;
  $: isCold = workflowStatus?.coldCheck?.isCold ?? false;
  $: isPending =
    statusKey === "PendingWon" ||
    statusKey === "PendingLost" ||
    statusKey === "PendingSent" ||
    statusKey === "PendingRevision" ||
    statusKey === "ReadyToSend" ||
    statusKey === "PendingNew";
  $: isPendingOutcome =
    statusKey === "PendingWon" || statusKey === "PendingLost";
  $: canFinalize = permissions["sales.opportunity.finalize"] !== false;
  $: canWin = permissions["sales.opportunity.win"] === true;
  $: canLose = permissions["sales.opportunity.lose"] === true;
  $: canCancel = permissions["sales.opportunity.cancel"] !== false;
  $: canReview = permissions["sales.opportunity.review"] !== false;
  $: canSend = permissions["sales.opportunity.send"] !== false;
  $: canReopen = permissions["sales.opportunity.reopen"] !== false;
  $: hasQuotes = quotes.length > 0;

  /** "Add Time" is available on all statuses except terminal/pending-outcome/canceled */
  $: canShowAddTime = statusKey
    ? !ADD_TIME_EXCLUDED_STATUSES.has(statusKey) && isOptimaStage
    : false;

  /** Open (unclosed) schedule entries for this opportunity */
  $: openScheduleEntries = activities
    .filter((a) => {
      const optimaType = a.customFields?.find(
        (f) => f.caption === "Optima_Type" || f.id === 45,
      )?.value;
      return optimaType === "Schedule Entry" && a.status?.id !== 2;
    })
    .sort((a, b) => (a.dateStart ?? "").localeCompare(b.dateStart ?? ""));

  /** For resendQuote: check that a quote was generated after the last revision opening */
  $: hasQuoteSinceRevision = (() => {
    if (!hasQuotes) return false;
    // Find the most recent "Revision" or "beginRevision" activity by looking at
    // customFields Optima_Type === "Revision" on activities
    const revisionActivities = activities.filter((a) => {
      const optimaType = a.customFields?.find(
        (f) => f.caption === "Optima_Type",
      )?.value;
      return optimaType === "Revision";
    });
    if (revisionActivities.length === 0) return true; // no revisions, any quote is fine
    // Get the most recent revision date
    const latestRevisionDate = revisionActivities.reduce((latest, a) => {
      const d = a.cwDateEntered ?? a.dateStart ?? "";
      return d > latest ? d : latest;
    }, "");
    if (!latestRevisionDate) return true;
    // Check if any quote was created after the latest revision
    return quotes.some((q) => q.createdAt > latestRevisionDate);
  })();

  /** Reason text for disabled send/resend buttons */
  $: sendQuoteDisabledReason = !hasQuotes
    ? "Generate a quote before sending"
    : null;
  $: resendQuoteDisabledReason = !hasQuotes
    ? "Generate a quote before sending"
    : !hasQuoteSinceRevision
      ? "Generate a new quote before resending"
      : null;

  $: availableActions = (
    workflowStatus?.availableActions?.filter((a) => a.permitted) ?? []
  ).filter((a) => actionPermitted(a.action));

  /** Synthesize a resurrect action for PendingWon/PendingLost when user has finalize perm */
  $: resurrectFromPending =
    isPendingOutcome &&
    canFinalize &&
    !availableActions.some((a) => a.action === "resurrect")
      ? ({
          action: "resurrect" as WorkflowAction,
          label: "Open for Revision",
          targetStatuses: [{ key: "Active", id: 58 }],
          requiresNote: true,
          requiresPermission: "sales.opportunity.finalize",
          permitted: true,
          payloadHints: {} as Record<string, string>,
        } satisfies WorkflowAvailableAction)
      : null;

  /** All actions including the synthesized resurrect */
  $: allActions = resurrectFromPending
    ? [...availableActions, resurrectFromPending]
    : availableActions;

  /** Map workflow action names to their required permission */
  function actionPermitted(action: WorkflowAction): boolean {
    switch (action) {
      case "requestReview":
      case "reviewDecision":
        return canReview;
      case "sendQuote":
      case "ReadyToSend":
      case "resendQuote":
        return canSend;
      case "finalize":
        return canFinalize || canWin || canLose;
      case "cancel":
        return canCancel;
      case "reopen":
        return canReopen;
      case "resurrect":
        // From PendingWon/PendingLost requires finalize perm; from terminal requires reopen
        return (isPendingOutcome && canFinalize) || canReopen;
      default:
        return true; // confirmQuote, beginRevision, acceptNew — base workflow perm
    }
  }

  /** CSS class for the workflow status badge */
  function workflowStatusClass(key: string | null): string {
    if (!key) return "wf-status-default";
    const map: Record<string, string> = {
      PendingNew: "wf-status-pending-new",
      New: "wf-status-new",
      InternalReview: "wf-status-review",
      QuoteSent: "wf-status-quote-sent",
      ConfirmedQuote: "wf-status-quote-confirmed",
      Active: "wf-status-active",
      ReadyToSend: "wf-status-ready-to-send",
      PendingSent: "wf-status-pending-sent",
      PendingRevision: "wf-status-pending-revision",
      PendingWon: "wf-status-pending-won",
      Won: "wf-status-won",
      PendingLost: "wf-status-pending-lost",
      Lost: "wf-status-lost",
      Canceled: "wf-status-canceled",
    };
    return map[key] ?? "wf-status-default";
  }

  /** Forward-progression actions in priority order */
  const FORWARD_ACTIONS: WorkflowAction[] = [
    "acceptNew",
    "requestReview",
    "reviewDecision",
    "sendQuote",
    "ReadyToSend",
    "resendQuote",
    "confirmQuote",
    "beginRevision",
  ];

  /** Get display label for an action */
  function actionLabel(action: WorkflowAvailableAction): string {
    // Context-dependent label for resurrect
    if (action.action === "resurrect" && isPendingOutcome) {
      return "Open for Revision";
    }
    const overrides: Partial<Record<WorkflowAction, string>> = {
      requestReview: "Request Review",
      reviewDecision: "Complete Review",
      sendQuote: "Mark Quote Sent",
      ReadyToSend: "Ready to Send",
      resendQuote: "Mark Quote Resent",
      confirmQuote: "Quote Confirmed",
      beginRevision: "Begin Revising",
      resurrect: "Resurrect",
      cancel: "Cancel",
      reopen: "Reopen",
      acceptNew: "Accept",
      sendBackForRevision: "Send Back for Revision",
      createScheduleEntry: "Create Schedule Entry",
    };
    return overrides[action.action] ?? action.label;
  }

  /** Open the appropriate modal for an action */
  function openAction(action: WorkflowAvailableAction) {
    workflowError = null;
    activeModal = action.action;
  }

  function closeModal() {
    activeModal = null;
    workflowError = null;
    preselectedOutcome = null;
  }

  /** Submit a workflow action */
  async function submitAction(
    action: WorkflowAction,
    payload: WorkflowActionPayload,
  ) {
    isSubmitting = true;
    workflowError = null;

    try {
      const json = await clientFetch<{
        successful: boolean;
        message?: string;
        data?: { error?: string };
      }>(`/sales/opportunity/${opportunityId}/workflow`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ action, payload }),
      });
      if (json.successful === false) {
        workflowError =
          json.message ?? json.data?.error ?? "Workflow action failed";
        return null;
      }

      // Success — close modal, merge new activities for immediate gating update
      closeModal();
      const result = json.data as WorkflowResult;
      if (result.activitiesCreated?.length) {
        activities = [...result.activitiesCreated, ...activities];
      }

      // Fetch fresh workflow status immediately so the parent can update without a full reload
      let freshWorkflowStatus: WorkflowStatusResponse | null = null;
      const expectedStatusId = result.newStatusId;
      const maxRetries = 2;
      for (let attempt = 0; attempt <= maxRetries; attempt++) {
        try {
          if (attempt > 0) {
            await new Promise((r) => setTimeout(r, 400 * attempt));
          }
          const statusJson = await clientFetch<{ data: WorkflowStatusResponse }>(
            `/sales/opportunity/${opportunityId}/workflow`,
          );
          freshWorkflowStatus = statusJson.data ?? null;
          // If the fresh status matches the expected new state, we're done
          if (
            !expectedStatusId ||
            freshWorkflowStatus?.currentStatusId === expectedStatusId
          ) {
            break;
          }
          // Stale data — retry
          freshWorkflowStatus = null;
        } catch {
          // Fetch failed — retry
        }
      }

      dispatch("workflowChanged", { result, freshWorkflowStatus });
      return result;
    } catch (err) {
      workflowError =
        err instanceof Error ? err.message : "Workflow action failed";
      return null;
    } finally {
      isSubmitting = false;
    }
  }

  /** Handle SendQuote modal wanting to chain into review */
  function handleSendQuoteChain(e: CustomEvent<{ action: WorkflowAction }>) {
    activeModal = e.detail.action;
  }

  /** Open the Add Time modal */
  function openAddTimeModal() {
    showAddTimeModal = true;
  }

  /** Handle successful time submission from AddTimeModal */
  function handleAddTimeSuccess() {
    showAddTimeModal = false;
    dispatch("workflowChanged", {
      result: {
        success: true,
        previousStatusId: workflowStatus?.currentStatusId ?? null,
        newStatusId: workflowStatus?.currentStatusId ?? null,
        previousStatus: null,
        newStatus: null,
        activitiesCreated: [],
        coldCheck: null,
        error: null,
      },
      freshWorkflowStatus: null,
    });
  }

  /** Submit a Create Schedule Entry action */
  async function submitScheduleEntry(payload: WorkflowActionPayload) {
    isScheduleEntrySubmitting = true;
    scheduleEntryError = null;
    try {
      const json = await clientFetch<{
        successful: boolean;
        message?: string;
        data?: { error?: string };
      }>(`/sales/opportunity/${opportunityId}/workflow`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ action: "createScheduleEntry", payload }),
      });

      if (json.successful === false) {
        scheduleEntryError = json.message ?? json.data?.error ?? "Failed to create schedule entry.";
        return;
      }

      showScheduleEntryModal = false;
      const result = json.data as WorkflowResult;
      if (result?.activitiesCreated?.length) {
        activities = [...result.activitiesCreated, ...activities];
      }

      // Fetch fresh workflow status
      let freshWorkflowStatus: WorkflowStatusResponse | null = null;
      try {
        const statusJson = await clientFetch<{ data: WorkflowStatusResponse }>(
          `/sales/opportunity/${opportunityId}/workflow`,
        );
        freshWorkflowStatus = statusJson.data ?? null;
      } catch { /* ignore */ }

      dispatch("workflowChanged", { result: result ?? { success: true, previousStatusId: null, newStatusId: null, previousStatus: null, newStatus: null, activitiesCreated: [], coldCheck: null, error: null }, freshWorkflowStatus });
    } catch (err) {
      scheduleEntryError = err instanceof Error ? err.message : "Failed to create schedule entry.";
    } finally {
      isScheduleEntrySubmitting = false;
    }
  }

  /** Determine if action needs a special modal */
  function isSpecialModal(action: WorkflowAction): boolean {
    return ["sendQuote", "resendQuote", "reviewDecision", "finalize"].includes(
      action,
    );
  }

  /** Actions that need a confirmation dialog before submission */
  function needsConfirmation(action: WorkflowAction): boolean {
    return action === "cancel" || action === "reopen" || action === "resurrect";
  }

  /** Confirmation messages */
  function confirmationMessage(action: WorkflowAction): string {
    if (action === "cancel") {
      return "This cannot be undone unless the opportunity is re-opened. Are you sure?";
    }
    if (action === "reopen") {
      return "Re-opening will set status to Active and log a full audit trail entry. Continue?";
    }
    if (action === "resurrect") {
      return "This will move the opportunity back to Active for further revision. Continue?";
    }
    return "";
  }

  /** Get the finalize actions split by outcome (only after quote confirmed, gated by win/lose perms) */
  $: finalizeWonAction =
    quoteConfirmed && canWin
      ? allActions.find(
          (a) =>
            a.action === "finalize" &&
            (a.payloadHints as Record<string, string>)?.["outcome"] === '"won"',
        )
      : undefined;
  $: finalizeLostAction =
    quoteConfirmed && canLose
      ? allActions.find(
          (a) =>
            a.action === "finalize" &&
            (a.payloadHints as Record<string, string>)?.["outcome"] ===
              '"lost"',
        )
      : undefined;
  $: nonFinalizeActions = allActions
    .filter((a) => a.action !== "finalize")
    .filter((a, i, arr) => arr.findIndex((b) => b.action === a.action) === i);

  /** The main forward-progression action (shown as filled primary button) */
  $: primaryAction =
    nonFinalizeActions.find((a) => FORWARD_ACTIONS.includes(a.action)) ?? null;

  /** Everything else (shown as ghost buttons) */
  $: secondaryActions = nonFinalizeActions.filter((a) => a !== primaryAction);
</script>

{#if workflowStatus && isOptimaStage}
  <div class="wf-panel" class:wf-panel-inline={inline}>
    <!-- Error Banner -->
    {#if workflowError}
      <div class="wf-error-banner">
        <span class="wf-error-text">{workflowError}</span>
        <button
          class="wf-error-dismiss"
          on:click={() => (workflowError = null)}
          aria-label="Dismiss error"
        >
          <svg
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            width="14"
            height="14"
          >
            <line x1="18" y1="6" x2="6" y2="18" /><line
              x1="6"
              y1="6"
              x2="18"
              y2="18"
            />
          </svg>
        </button>
      </div>
    {/if}

    <!-- Action Buttons -->
    {#if !isTerminal && allActions.length > 0}
      <div class="wf-actions">
        <!-- Primary forward action (filled button) -->
        {#if primaryAction}
          {@const isSendGated =
            primaryAction.action === "sendQuote" && !!sendQuoteDisabledReason}
          {@const isResendGated =
            primaryAction.action === "resendQuote" &&
            !!resendQuoteDisabledReason}
          {@const gatedReason = isSendGated
            ? sendQuoteDisabledReason
            : isResendGated
              ? resendQuoteDisabledReason
              : null}
          {#if gatedReason}
            <span class="wf-tooltip-wrap" data-tooltip={gatedReason}>
              <button class="wf-action-btn wf-btn-primary" disabled
                >{actionLabel(primaryAction)}</button
              >
            </span>
          {:else}
            <button
              class="wf-action-btn wf-btn-primary"
              on:click={() => openAction(primaryAction)}
              disabled={isSubmitting}>{actionLabel(primaryAction)}</button
            >
          {/if}
        {/if}

        <!-- Secondary actions + finalize (ghost buttons) -->
        {#if secondaryActions.length > 0 || finalizeWonAction || finalizeLostAction}
          {#if primaryAction}
            <span class="wf-action-sep" aria-hidden="true"></span>
          {/if}

          {#each secondaryActions as action, i (action.action + "-" + i)}
            {@const secSendGated =
              action.action === "sendQuote" && !!sendQuoteDisabledReason}
            {@const secResendGated =
              action.action === "resendQuote" && !!resendQuoteDisabledReason}
            {@const secGatedReason = secSendGated
              ? sendQuoteDisabledReason
              : secResendGated
                ? resendQuoteDisabledReason
                : null}
            {#if secGatedReason}
              <span class="wf-tooltip-wrap" data-tooltip={secGatedReason}>
                <button class="wf-action-btn wf-btn-ghost" disabled
                  >{actionLabel(action)}</button
                >
              </span>
            {:else}
              <button
                class="wf-action-btn wf-btn-ghost"
                class:wf-ghost-danger={action.action === "cancel"}
                on:click={() => openAction(action)}
                disabled={isSubmitting}>{actionLabel(action)}</button
              >
            {/if}
          {/each}

          {#if finalizeWonAction}
            <button
              class="wf-action-btn wf-btn-ghost wf-ghost-success"
              on:click={() => {
                preselectedOutcome = "won";
                openAction(finalizeWonAction);
              }}
              disabled={isSubmitting}
            >
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2.5"
                width="11"
                height="11"><polyline points="20 6 9 17 4 12" /></svg
              >
              Won
            </button>
          {/if}
          {#if finalizeLostAction}
            <button
              class="wf-action-btn wf-btn-ghost wf-ghost-danger"
              on:click={() => {
                preselectedOutcome = "lost";
                openAction(finalizeLostAction);
              }}
              disabled={isSubmitting}
            >
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2.5"
                width="11"
                height="11"
                ><line x1="18" y1="6" x2="6" y2="18" /><line
                  x1="6"
                  y1="6"
                  x2="18"
                  y2="18"
                /></svg
              >
              Lost
            </button>
          {/if}
        {/if}

        <!-- Add Time + Create Schedule Entry buttons (right side) -->
        {#if canShowAddTime || true}
          <span class="wf-action-sep" aria-hidden="true"></span>
          <!-- Create Schedule Entry (calendar icon) -->
          <span class="wf-tooltip-wrap" data-tooltip="Create Schedule Entry">
            <button
              class="wf-action-btn wf-btn-icon"
              on:click={() => { showScheduleEntryModal = true; scheduleEntryError = null; }}
              disabled={isSubmitting || isScheduleEntrySubmitting}
              aria-label="Create Schedule Entry"
            >
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="15" height="15">
                <rect x="3" y="4" width="18" height="18" rx="2" ry="2" />
                <line x1="16" y1="2" x2="16" y2="6" />
                <line x1="8" y1="2" x2="8" y2="6" />
                <line x1="3" y1="10" x2="21" y2="10" />
              </svg>
            </button>
          </span>
          <!-- Add Time (clock icon) -->
          {#if canShowAddTime}
            <span class="wf-tooltip-wrap" data-tooltip="Add Time">
              <button
                class="wf-action-btn wf-btn-icon"
                on:click={openAddTimeModal}
                disabled={isSubmitting || isLoadingActivities}
                aria-label="Add Time"
              >
                {#if isLoadingActivities}
                  <span class="wf-spinner wf-spinner-sm"></span>
                {:else}
                  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="15" height="15">
                    <circle cx="12" cy="12" r="10" /><polyline points="12 6 12 12 16 14" />
                  </svg>
                {/if}
              </button>
            </span>
          {/if}
        {/if}
      </div>
    {/if}

    <!-- Pending schedule entries -->
    {#if openScheduleEntries.length > 0}
      <div class="wf-schedule-entries">
        {#each openScheduleEntries as entry}
          <div class="wf-se-item">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="12" height="12" class="wf-se-icon">
              <rect x="3" y="4" width="18" height="18" rx="2" ry="2" />
              <line x1="16" y1="2" x2="16" y2="6" />
              <line x1="8" y1="2" x2="8" y2="6" />
              <line x1="3" y1="10" x2="21" y2="10" />
            </svg>
            <span class="wf-se-name">{entry.name ?? "Schedule Entry"}</span>
            {#if entry.dateStart}
              <span class="wf-se-time">
                {formatDateTime(entry.dateStart)}{#if entry.dateEnd}&nbsp;–&nbsp;{formatDateTime(entry.dateEnd)}{/if}
              </span>
            {/if}
          </div>
        {/each}
      </div>
    {/if}

    <!-- Terminal / Locked indicator -->
    {#if isTerminal}
      <div class="wf-terminal-notice">
        <svg
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
          width="14"
          height="14"
        >
          <rect x="3" y="11" width="18" height="11" rx="2" ry="2" /><path
            d="M7 11V7a5 5 0 0110 0v4"
          />
        </svg>
        This opportunity is finalized and locked.
      </div>
    {/if}
  </div>
{/if}

<!-- ── Modals ── -->

<!-- Generic action modal (requestReview, confirmQuote, beginRevision, resurrect, cancel, reopen, acceptNew) -->
{#if activeModal && !isSpecialModal(activeModal)}
  {@const action = allActions.find((a) => a.action === activeModal)}
  {#if action}
    <WorkflowActionModal
      isOpen={true}
      title={actionLabel(action)}
      actionName={action.action}
      requiresNote={action.requiresNote}
      needsConfirmation={needsConfirmation(action.action)}
      confirmationMessage={confirmationMessage(action.action)}
      isDestructive={action.action === "cancel"}
      error={workflowError}
      {isSubmitting}
      on:submit={(e) => submitAction(action.action, e.detail)}
      on:close={closeModal}
    />
  {/if}
{/if}

<!-- SendQuote modal -->
{#if activeModal === "sendQuote" || activeModal === "resendQuote"}
  <SendQuoteModal
    isOpen={true}
    {canFinalize}
    error={workflowError}
    {isSubmitting}
    actionName={activeModal}
    on:submit={(e) => submitAction(activeModal ?? "sendQuote", e.detail)}
    on:close={closeModal}
  />
{/if}

<!-- ReviewDecision modal -->
{#if activeModal === "reviewDecision"}
  <ReviewDecisionModal
    isOpen={true}
    {canCancel}
    {canSend}
    error={workflowError}
    {isSubmitting}
    on:submit={(e) => submitAction("reviewDecision", e.detail)}
    on:sendQuote={() => {
      activeModal = "sendQuote";
    }}
    on:close={closeModal}
  />
{/if}

<!-- Finalize modal -->
{#if activeModal === "finalize"}
  {@const wonAction = finalizeWonAction}
  {@const lostAction = finalizeLostAction}
  <FinalizeModal
    isOpen={true}
    {statusKey}
    hasWon={!!wonAction}
    hasLost={!!lostAction}
    {canFinalize}
    initialOutcome={preselectedOutcome}
    error={workflowError}
    {isSubmitting}
    on:submit={(e) => submitAction("finalize", e.detail)}
    on:close={closeModal}
  />
{/if}

<!-- Add Time modal -->
<AddTimeModal
  isOpen={showAddTimeModal}
  {opportunityId}
  on:success={handleAddTimeSuccess}
  on:close={() => { showAddTimeModal = false; }}
  on:createScheduleEntry={() => { showAddTimeModal = false; showScheduleEntryModal = true; }}
/>

<!-- Create Schedule Entry modal -->
<CreateScheduleEntryModal
  isOpen={showScheduleEntryModal}
  isSubmitting={isScheduleEntrySubmitting}
  error={scheduleEntryError}
  on:submit={(e) => submitScheduleEntry(e.detail)}
  on:close={() => { showScheduleEntryModal = false; scheduleEntryError = null; }}
/>
