<script lang="ts">
  import "../../../../styles/sales/opportunitydetail.css";
  import { onMount } from "svelte";
  import { invalidateAll } from "$app/navigation";
  import type { PageData } from "./types";
  import {
    STATUS_ID_TO_KEY,
    TERMINAL_STATUSES,
    EDITABLE_STATUSES,
    type WorkflowResult,
    type WorkflowStatusResponse,
  } from "$lib/optima-api/modules/sales";

  // Tab components
  import OpportunitySidebar from "./components/OpportunitySidebar.svelte";
  import OverviewTab from "./components/OverviewTab.svelte";
  import NotesTab from "./components/NotesTab.svelte";
  import ActivityTab from "./components/ActivityTab.svelte";
  import ProductsTab from "./components/ProductsTab.svelte";
  import QuotesTab from "./components/QuotesTab.svelte";
  import OpportunityReportsTab from "./components/OpportunityReportsTab.svelte";
  import DiscountsTab from "./components/DiscountsTab.svelte";
  import WorkflowPanel from "./components/WorkflowPanel.svelte";
  import UnsavedChangesDialog from "../../../../components/UnsavedChangesDialog.svelte";

  export let data: PageData;

  $: opportunity = data.opportunity;
  $: opportunityId = data.opportunityId;
  $: notes = data.notes;
  $: contacts = data.contacts;
  $: products = data.products;
  $: console.log("[OpportunityPage] full API response data:", data);
  $: quotes = data.quotes ?? [];
  $: permissions = data.permissions;

  // workflowStatus can be locally overridden after a workflow action for instant UI update.
  // Uses the same override pattern as localActivities so that Svelte 5's $: pre-effects
  // don't clobber the manual assignment during the same update flush.
  let workflowStatusOverride: WorkflowStatusResponse | null = null;
  $: if (data.workflowStatus !== undefined) workflowStatusOverride = null; // reset on server data refresh
  $: workflowStatus = workflowStatusOverride ?? data.workflowStatus ?? null;

  // activities can be speculatively updated with newly created activities from workflow actions
  let localActivities: typeof opportunity.activities | null = null;
  $: if (data.opportunity) localActivities = null; // reset when server data refreshes
  $: effectiveActivities = localActivities ?? opportunity?.activities ?? [];

  // ActivityTab ref — used to trigger a refresh after workflow actions create new activities
  let activityTabComponent: ActivityTab;
  // NotesTab ref — refresh after workflow actions
  let notesTabComponent: NotesTab;

  // Closed opportunity lockdown – no edits except admin delete.
  // Also immediately reflects Won/Lost/Canceled workflow status without needing a reload.
  $: isClosedOpportunity = (() => {
    const wfKey = workflowStatus
      ? (STATUS_ID_TO_KEY[workflowStatus.currentStatusId] ?? null)
      : null;
    if (wfKey && TERMINAL_STATUSES.has(wfKey)) return true;
    if (!opportunity) return false;
    const statusText =
      `${opportunity.status?.name ?? ""} ${opportunity.type?.name ?? ""}`.toLowerCase();
    return (
      !!opportunity.closedFlag ||
      !!opportunity.closedDate ||
      statusText.includes("won") ||
      statusText.includes("lost")
    );
  })();

  /**
   * Quote generation is only blocked in truly terminal states (Won/Lost).
   * All other workflow states — including PendingWon, PendingLost, etc. —
   * allow generating a quote. Outside the Optima workflow, fall back to
   * the standard isClosedOpportunity check.
   */
  $: isQuoteGenerationBlocked = (() => {
    const wfKey = workflowStatus
      ? (STATUS_ID_TO_KEY[workflowStatus.currentStatusId] ?? null)
      : null;
    if (wfKey) return TERMINAL_STATUSES.has(wfKey);
    return isClosedOpportunity;
  })();

  /**
   * True when the opportunity is in the Optima workflow and in a state
   * other than New or Active, meaning back-generate permission is required.
   */
  $: isBackGenerateState = (() => {
    if (!workflowStatus?.isOptimaStage) return false;
    const wfKey = STATUS_ID_TO_KEY[workflowStatus.currentStatusId] ?? null;
    if (!wfKey) return false;
    return !EDITABLE_STATUSES.has(wfKey);
  })();

  // Workflow read-only: only New and Active are editable (when in Optima workflow).
  $: isReadOnly = (() => {
    if (isClosedOpportunity) return true;
    const wfStatus = workflowStatus;
    if (!wfStatus?.isOptimaStage) return false;
    const key = STATUS_ID_TO_KEY[wfStatus.currentStatusId] ?? null;
    if (!key) return false;
    return !EDITABLE_STATUSES.has(key);
  })();

  /** Handle a completed workflow action: update UI immediately without a full page reload. */
  function handleWorkflowChanged(
    e: CustomEvent<{ result: WorkflowResult; freshWorkflowStatus: WorkflowStatusResponse | null }>,
  ) {
    const { result, freshWorkflowStatus } = e.detail;

    // Update workflow status immediately so badges and action buttons reflect the new state
    if (freshWorkflowStatus) {
      workflowStatusOverride = freshWorkflowStatus;
    } else if (result.newStatusId !== null) {
      // Optimistic update using only the data in the action response
      workflowStatusOverride = {
        ...(workflowStatus ?? ({} as WorkflowStatusResponse)),
        currentStatusId: result.newStatusId,
        currentStatus: result.newStatus ?? "",
        coldCheck: result.coldCheck,
        availableActions: workflowStatus?.availableActions ?? [],
      };
    }

    // Prepend newly created activities so the Activity tab updates immediately
    if (result.activitiesCreated?.length) {
      localActivities = [
        ...result.activitiesCreated,
        ...(localActivities ?? opportunity?.activities ?? []),
      ];
      activityTabComponent?.refresh();
      notesTabComponent?.refresh();
    }
  }

  let localProductSequence: number[] | null =
    data.opportunity?.productSequence ?? null;

  $: if (Array.isArray(opportunity?.productSequence)) {
    localProductSequence = opportunity.productSequence;
  }

  // Mobile detection
  let isMobile = false;
  function checkMobile() {
    isMobile = typeof window !== "undefined" && window.innerWidth <= 768;
  }
  onMount(() => {
    checkMobile();
    console.log("[OpportunityLoad] Description values:", {
      description: (opportunity as Record<string, unknown> | null)?.description,
      notes: opportunity?.notes ?? null,
      name: opportunity?.name ?? null,
      opportunityId,
    });
    window.addEventListener("resize", checkMobile);
    return () => window.removeEventListener("resize", checkMobile);
  });

  // Tab navigation
  const tabs = [
    "Overview",
    "Products",
    "Discounts",
    "Quotes",
    "Notes",
    "Activity",
    "Reports",
  ] as const;
  type Tab = (typeof tabs)[number];
  let activeTab: Tab = "Overview";

  // Hide Quotes tab if user lacks fetch permission
  // Hide Reports tab if user lacks reports permission
  $: visibleTabs = tabs.filter((t) => {
    if (
      t === "Quotes" &&
      permissions["sales.opportunity.quote.fetch"] === false
    )
      return false;
    if (t === "Reports" && permissions["ui.navigation.reports.view"] === false)
      return false;
    return true;
  });

  // Track whether ProductsTab is in edit mode
  let productsEditing = false;

  // Unsaved order changes dialog
  let showOrderGuardDialog = false;
  let pendingTabAction: (() => void) | null = null;

  function confirmDiscard() {
    const action = pendingTabAction;
    pendingTabAction = null;
    showOrderGuardDialog = false;
    productsEditing = false;
    action?.();
  }

  function cancelDiscard() {
    showOrderGuardDialog = false;
    pendingTabAction = null;
  }

  function guardedAction(action: () => void) {
    if (productsEditing) {
      pendingTabAction = action;
      showOrderGuardDialog = true;
    } else {
      action();
    }
  }

  /** Guard: block tab switch if ProductsTab has unsaved edits */
  function guardedSetTab(tab: Tab) {
    if (activeTab === tab) return;
    guardedAction(() => { activeTab = tab; });
  }

  // Product to auto-select when switching to Products tab
  let pendingProductId: number | null = null;

  // Quote to auto-select when switching to Quotes tab
  let pendingQuoteId: string | null = null;

  function handleSelectProduct(e: CustomEvent<number>) {
    pendingProductId = e.detail;
    guardedSetTab("Products");
  }

  function handleViewQuote(e: CustomEvent<string>) {
    pendingQuoteId = e.detail;
    guardedSetTab("Quotes");
  }

  function handleSequenceSaved(e: CustomEvent<number[]>) {
    localProductSequence = e.detail;
  }

  function handleProductsChanged(e: CustomEvent<PageData["products"]>) {
    products = e.detail;
  }

  function handleQuotesChanged(
    e: CustomEvent<import("$lib/optima-api/modules/sales").CommittedQuote[]>,
  ) {
    quotes = e.detail;
  }

  // Mobile nav state
  let mobileActiveTab: Tab | null = null;

  function selectMobileTab(tab: Tab) {
    guardedAction(() => { activeTab = tab; mobileActiveTab = tab; });
  }

  function mobileBack() {
    guardedAction(() => { mobileActiveTab = null; });
  }
</script>

<svelte:head>
  <title>{opportunity?.name ?? "Opportunity"} — Project Optima</title>
</svelte:head>

<div class="opportunity-detail-page">
  <!-- Left pane — Opportunity overview -->
  <OpportunitySidebar
    {opportunity}
    {isMobile}
    {mobileActiveTab}
    {permissions}
    isClosedOpportunity={isReadOnly}
    {workflowStatus}
    opportunityTypes={data.opportunityTypes ?? []}
    accessToken={data.accessToken}
    on:updated={() => invalidateAll()}
  />

  <!-- Mobile vertical nav menu -->
  {#if isMobile && mobileActiveTab === null}
    <div class="mobile-nav-menu">
      {#each visibleTabs as tab}
        <button
          class="mobile-nav-item"
          on:click={() => selectMobileTab(tab)}
          type="button"
        >
          <span class="mobile-nav-icon">
            {#if tab === "Products"}
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                width="20"
                height="20"
              >
                <path
                  d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"
                />
                <polyline points="3.27 6.96 12 12.01 20.73 6.96" />
                <line x1="12" y1="22.08" x2="12" y2="12" />
              </svg>
            {:else if tab === "Notes"}
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                width="20"
                height="20"
              >
                <path
                  d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"
                /><polyline points="14 2 14 8 20 8" /><line
                  x1="16"
                  y1="13"
                  x2="8"
                  y2="13"
                /><line x1="16" y1="17" x2="8" y2="17" />
              </svg>
            {:else if tab === "Quotes"}
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                width="20"
                height="20"
              >
                <path
                  d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"
                />
                <polyline points="14 2 14 8 20 8" />
                <line x1="8" y1="13" x2="16" y2="13" />
                <line x1="8" y1="17" x2="13" y2="17" />
              </svg>
            {:else}
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                width="20"
                height="20"
              >
                <polyline points="22 12 18 12 15 21 9 3 6 12 2 12" />
              </svg>
            {/if}
          </span>
          <span class="mobile-nav-label">{tab}</span>
          {#if tab === "Products" && products.length > 0}
            <span class="mobile-nav-badge">{products.length}</span>
          {/if}

          {#if tab === "Quotes" && quotes.length > 0}
            <span class="mobile-nav-badge">{quotes.length}</span>
          {/if}
          <svg
            class="mobile-nav-chevron"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            width="16"
            height="16"
          >
            <polyline points="9 18 15 12 9 6" />
          </svg>
        </button>
      {/each}
    </div>
  {/if}

  <!-- Right pane -->
  <div
    class="opportunity-detail-right"
    class:mobile-hidden={isMobile && mobileActiveTab === null}
  >
    <!-- Mobile content header with back button -->
    {#if isMobile && mobileActiveTab !== null}
      <div class="mobile-content-header">
        <button
          class="mobile-back-btn"
          on:click={mobileBack}
          type="button"
          aria-label="Back to menu"
        >
          <svg
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            width="18"
            height="18"
          >
            <path d="M19 12H5M12 19l-7-7 7-7" />
          </svg>
        </button>
        <h3 class="mobile-content-title">{mobileActiveTab}</h3>
      </div>
    {/if}

    <div class="tab-bar" role="tablist">
      {#each visibleTabs as tab}
        <button
          class="tab-btn"
          class:active={activeTab === tab}
          role="tab"
          aria-selected={activeTab === tab}
          on:click={() => guardedSetTab(tab)}
        >
          {tab}
          {#if tab === "Products" && products.length > 0}
            <span class="tab-count-badge">{products.length}</span>
          {/if}

          {#if tab === "Quotes" && quotes.length > 0}
            <span class="tab-count-badge">{quotes.length}</span>
          {/if}
        </button>
      {/each}

      <!-- Workflow actions pushed to right side of tab bar -->
      {#if opportunity && opportunityId}
        <WorkflowPanel
          {opportunity}
          {workflowStatus}
          {permissions}
          {opportunityId}
          {quotes}
          activities={effectiveActivities}
          inline={true}
          on:workflowChanged={handleWorkflowChanged}
        />
      {/if}
    </div>
    <div class="detail-pane-body">
      {#if activeTab === "Overview"}
        <OverviewTab
          {opportunity}
          {opportunityId}
          {notes}
          {contacts}
          {products}
          {permissions}
          on:selectProduct={handleSelectProduct}
          on:switchTab={(e) => guardedSetTab(e.detail as Tab)}
          on:viewQuote={handleViewQuote}
        />
      {:else if activeTab === "Products"}
        <ProductsTab
          {products}
          accessToken={data.accessToken}
          {opportunityId}
          productSequence={localProductSequence}
          initialProductId={pendingProductId}
          {permissions}
          isClosedOpportunity={isReadOnly}
          salesTaxRate={opportunity?.expectedSalesTaxRate ?? null}
          taxCodeDescription={opportunity?.taxCodeDescription ?? null}
          bind:isEditing={productsEditing}
          on:sequenceSaved={handleSequenceSaved}
          on:productsChanged={handleProductsChanged}
        />
      {:else if activeTab === "Discounts"}
        <DiscountsTab {products} />
      {:else if activeTab === "Quotes"}
        <QuotesTab
          accessToken={data.accessToken}
          opportunityId={data.opportunityId}
          initialQuotes={quotes}
          initialQuoteId={pendingQuoteId}
          {permissions}
          isClosedOpportunity={isQuoteGenerationBlocked}
          {isBackGenerateState}
          on:quotesChanged={handleQuotesChanged}
        />
      {:else if activeTab === "Notes"}
        <NotesTab
          bind:this={notesTabComponent}
          {opportunityId}
          activities={effectiveActivities}
        />
      {:else if activeTab === "Activity"}
        <ActivityTab
          bind:this={activityTabComponent}
          {opportunityId}
          activities={effectiveActivities}
          on:viewQuote={handleViewQuote}
        />
      {:else if activeTab === "Reports"}
        <OpportunityReportsTab {opportunity} {workflowStatus} {opportunityId} />
      {/if}
    </div>
  </div>
</div>

<UnsavedChangesDialog
  isOpen={showOrderGuardDialog}
  title="Unsaved Order Changes"
  message="You have unsaved product order changes. Discard them and continue?"
  onDiscard={confirmDiscard}
  onCancel={cancelDiscard}
/>
