<script lang="ts">
  import { goto, afterNavigate } from "$app/navigation";
  import { invalidateAll } from "$app/navigation";
  import type { PermissionMap } from "$lib/permissions";
  import type {
    MemberSalesMetrics,
    OpportunityType,
  } from "$lib/optima-api/modules/sales";
  import { formatDate } from "$lib/utils";
  import {
    statusColorClass,
    statusLabel,
    isEquivalencyStatus,
    originalStatusName,
  } from "$lib/sales-utils";
  import CreateOpportunityModal from "../../components/CreateOpportunityModal.svelte";
  import AccessDenied from "../../components/AccessDenied.svelte";
  import NoResultsMonkey from "../../components/NoResultsMonkey.svelte";
  import Pagination from "../../components/Pagination.svelte";
  import OpportunityContextMenu from "../../components/OpportunityContextMenu.svelte";
  import "../../styles/sales/sales.css";

  let contextMenu: OpportunityContextMenu;

  type SalesOpportunity = {
    id: string;
    cwOpportunityId?: number;
    name: string;
    type?: { id?: number; name?: string } | null;
    stage?: { id?: number; name?: string } | null;
    status?: { id?: number; name?: string } | null;
    priority?: { id?: number; name?: string } | null;
    interest?: "HOT" | "WARM" | "COLD" | null;
    primarySalesRep?: {
      id?: number;
      identifier?: string;
      name?: string;
    } | null;
    secondarySalesRep?: {
      id?: number;
      identifier?: string;
      name?: string;
    } | null;
    company?: { id?: string; name?: string } | null;
    expectedCloseDate?: string | null;
    closedDate?: string | null;
    closedFlag?: boolean;
    cwLastUpdated?: string | null;
    createdAt?: string;
    updatedAt?: string;
  };

  export let data: {
    permissions: PermissionMap;
    opportunities: SalesOpportunity[];
    opportunityTypes: OpportunityType[];
    totalPages: number;
    currentPage: number;
    totalRecords: number;
    search: string;
    includeClosed: boolean;
    dashSearch: string;
    dashIncludeClosed: boolean;
    tab: string;
    metrics: MemberSalesMetrics | null;
  };

  import { page } from "$app/stores";

  $: m = data.metrics;

  function fmt$(v: number | null | undefined): string {
    if (v == null) return "—";
    return new Intl.NumberFormat("en-US", {
      style: "currency",
      currency: "USD",
      maximumFractionDigits: 0,
    }).format(v);
  }
  function fmtPct(v: number | null | undefined): string {
    if (v == null) return "—";
    return (v * 100).toFixed(1) + "%";
  }
  function fmtDays(v: number | null | undefined): string {
    if (v == null || v === 0) return "—";
    return Math.round(v) + "d";
  }

  $: activeTab = (() => {
    const t = data.tab ?? (canViewMine ? "dashboard" : "opportunities");
    if (t === "dashboard" && !canViewMine) return "opportunities";
    if (t === "opportunities" && !canViewAll) return "dashboard";
    return t;
  })();
  $: currentUser = $page.data.user as {
    name?: string;
    cwIdentifier?: string;
  } | null;
  $: myIdentifier = currentUser?.cwIdentifier;
  let dashSearch = "";
  let dashHideClosed = !data.dashIncludeClosed;
  function handleDashSearchKeydown(e: KeyboardEvent) {
    if (e.key === "Tab" && !e.shiftKey) {
      const input = e.currentTarget as HTMLElement;
      const table = input
        .closest(".dash-section")
        ?.querySelector<HTMLElement>("tbody tr");
      if (table) {
        e.preventDefault();
        table.focus();
      }
    }
  }
  function navigateDashFilters(hideClosed = dashHideClosed) {
    const params = new URLSearchParams();
    params.set("tab", "dashboard");
    if (!hideClosed) params.set("dashIncludeClosed", "true");
    goto(`/sales?${params.toString()}`, {
      replaceState: false,
      keepFocus: true,
      noScroll: true,
    });
  }
  $: filteredMyOpportunities = dashSearch.trim()
    ? opportunities.filter((op) => {
        const q = dashSearch.toLowerCase();
        return (
          op.name?.toLowerCase().includes(q) ||
          op.company?.name?.toLowerCase().includes(q) ||
          op.cwOpportunityId?.toString().includes(q) ||
          op.status?.name?.toLowerCase().includes(q)
        );
      })
    : opportunities;
  $: myOpenOpps = opportunities.filter((op) => !op.closedFlag);

  function switchTab(tab: string) {
    if (tab === "dashboard") {
      goto("/sales?tab=dashboard");
    } else {
      goto("/sales?tab=opportunities&page=1");
    }
  }

  $: hasAccess = data.permissions["sales.opportunity.fetch.many"] === true;
  $: canCreate = data.permissions["sales.opportunity.create"] === true;
  $: canViewAll = data.permissions["sales.opportunity.fetch.all"] === true;
  $: canViewMine = data.permissions["sales.opportunity.fetch.@me"] === true;

  let showCreateModal = false;

  let searchInput = data.search;
  let debounceTimer: ReturnType<typeof setTimeout>;
  let isSearching = false;
  let searchInputEl: HTMLInputElement;
  let searchStartedAt = 0;
  let isUserTyping = false;
  let lastAutoOpenSearch = "";
  let autoOpenTimer: ReturnType<typeof setTimeout>;

  let showClosed = data.includeClosed;
  let filterOpen = false;
  let filterBtnEl: HTMLButtonElement;
  let filterPopoverEl: HTMLDivElement;

  let dashFilterOpen = false;
  let dashFilterBtnEl: HTMLButtonElement;
  let dashFilterPopoverEl: HTMLDivElement;

  function toggleDashFilterPopover() {
    dashFilterOpen = !dashFilterOpen;
  }

  function handleDashFilterClickOutside(e: MouseEvent) {
    if (!dashFilterOpen) return;
    const target = e.target as Node;
    if (
      dashFilterBtnEl?.contains(target) ||
      dashFilterPopoverEl?.contains(target)
    )
      return;
    dashFilterOpen = false;
  }

  function toggleFilterPopover() {
    filterOpen = !filterOpen;
  }

  function handleFilterClickOutside(e: MouseEvent) {
    if (!filterOpen) return;
    const target = e.target as Node;
    if (filterBtnEl?.contains(target) || filterPopoverEl?.contains(target))
      return;
    filterOpen = false;
  }

  function toggleClosed() {
    showClosed = !showClosed;
    filterOpen = false;
    navigateWithFilters({ page: 1 });
  }

  $: activeFilterCount = showClosed ? 0 : 1;

  afterNavigate(() => {
    const elapsed = Date.now() - searchStartedAt;
    const remaining = Math.max(0, 500 - elapsed);
    setTimeout(() => {
      isSearching = false;
      isUserTyping = false;
      if (searchInputEl && document.activeElement !== searchInputEl) {
        requestAnimationFrame(() => searchInputEl?.focus());
      }
    }, remaining);
  });

  // Auto-open: when the server-confirmed search returns exactly 1 result
  // whose CW opportunity ID matches the search term, navigate to it.
  $: {
    const serverSearch = data.search?.trim() || "";
    if (
      serverSearch &&
      serverSearch !== lastAutoOpenSearch &&
      data.opportunities.length === 1
    ) {
      const opp = data.opportunities[0];
      const cwId =
        opp.cwOpportunityId != null ? String(opp.cwOpportunityId) : null;
      const normalized = serverSearch.replace(/^(?:cw\s*#?|#)\s*/i, "");
      if (cwId && normalized === cwId) {
        lastAutoOpenSearch = serverSearch;
        clearTimeout(autoOpenTimer);
        autoOpenTimer = setTimeout(() => {
          goto(`/sales/opportunity/${opp.id}?from=opportunities`);
        }, 600);
      }
    }
  }

  $: currentPage = data.currentPage;
  $: totalPages = data.totalPages;
  $: totalRecords = data.totalRecords;
  $: opportunities = data.opportunities;

  function navigateWithFilters(
    opts: { page?: number; keepFocus?: boolean } = {}
  ) {
    const params = new URLSearchParams();
    params.set("page", String(opts.page ?? currentPage));
    if (searchInput) params.set("search", searchInput);
    if (!showClosed) params.set("includeClosed", "false");
    goto(`/sales?tab=opportunities&${params.toString()}`, {
      replaceState: true,
      keepFocus: opts.keepFocus ?? false,
      noScroll: true,
    });
  }

  function navigateToPage(p: number) {
    navigateWithFilters({ page: p });
  }

  function handleSearch() {
    isUserTyping = true;
    searchStartedAt = Date.now();
    clearTimeout(debounceTimer);
    clearTimeout(autoOpenTimer);
    debounceTimer = setTimeout(() => {
      isSearching = true;
      isUserTyping = false;
      navigateWithFilters({ page: 1, keepFocus: true });
    }, 500);
  }

  function handleKeydown(e: KeyboardEvent) {
    if (e.key === "Enter") {
      isSearching = true;
      isUserTyping = false;
      searchStartedAt = Date.now();
      clearTimeout(debounceTimer);
      clearTimeout(autoOpenTimer);
      navigateWithFilters({ page: 1, keepFocus: true });
    }
    if (e.key === "Tab" && !e.shiftKey) {
      const input = e.currentTarget as HTMLElement;
      const table = input
        .closest(".sales-body, .dash-section")
        ?.querySelector<HTMLElement>("tbody tr");
      if (table) {
        e.preventDefault();
        table.focus();
      }
    }
  }

  function handleRowKeydown(
    e: KeyboardEvent,
    oppId: string | number,
    from: "dashboard" | "opportunities"
  ) {
    const row = e.currentTarget as HTMLElement;
    if (e.key === "Enter" || e.key === " ") {
      e.preventDefault();
      goto(`/sales/opportunity/${oppId}?from=${from}`);
    } else if (e.key === "ArrowDown") {
      e.preventDefault();
      (row.nextElementSibling as HTMLElement | null)?.focus();
    } else if (e.key === "ArrowUp") {
      e.preventDefault();
      const prev = row.previousElementSibling as HTMLElement | null;
      if (prev) {
        prev.focus();
      } else {
        // back to search input
        const input = row
          .closest(".sales-body, .dash-section")
          ?.querySelector<HTMLElement>("input[type=search], input[type=text]");
        input?.focus();
      }
    } else if (e.key === "Escape") {
      const input = row
        .closest(".sales-body, .dash-section")
        ?.querySelector<HTMLElement>("input[type=search], input[type=text]");
      input?.focus();
    }
  }

  function ownerLabel(op: SalesOpportunity): string {
    return (
      op.primarySalesRep?.name ||
      op.primarySalesRep?.identifier ||
      op.secondarySalesRep?.name ||
      op.secondarySalesRep?.identifier ||
      "—"
    );
  }

  function companyLabel(op: SalesOpportunity): string {
    return op.company?.name || "—";
  }

  function ratingHeatClass(name: string | undefined): string {
    if (!name) return "heat-neutral";
    const n = name.toLowerCase();
    if (n.includes("hot")) return "heat-hot";
    if (n.includes("warm") || n.includes("medium")) return "heat-warm";
    if (n.includes("cold") || n.includes("cool")) return "heat-cold";
    return "heat-neutral";
  }

  function ratingHeatLevel(name: string | undefined): number {
    if (!name) return 0;
    const n = name.toLowerCase();
    if (n.includes("hot")) return 3;
    if (n.includes("warm") || n.includes("medium")) return 2;
    if (n.includes("cold") || n.includes("cool")) return 1;
    return 0;
  }

  function heatDotColor(name: string | undefined): string {
    if (!name) return "rgba(128,128,128,0.4)";
    const n = name.toLowerCase();
    if (n.includes("hot")) return "#ef4444";
    if (n.includes("warm") || n.includes("medium")) return "#f59e0b";
    if (n.includes("cold") || n.includes("cool")) return "#38bdf8";
    return "rgba(128,128,128,0.4)";
  }

  function getDotStyle(level: number, ratingName: string | undefined): string {
    const lvl = ratingHeatLevel(ratingName);
    const filled = level <= lvl;
    if (!filled)
      return "background: rgba(128,128,128,0.25); width: 7px; height: 7px; border-radius: 50%; display: inline-block;";
    const color = heatDotColor(ratingName);
    let s = `background: ${color}; width: 7px; height: 7px; border-radius: 50%; display: inline-block;`;
    if (ratingHeatClass(ratingName) === "heat-hot")
      s += " box-shadow: 0 0 4px rgba(239,68,68,0.6);";
    return s;
  }
</script>

<svelte:window
  on:click={(e) => {
    handleFilterClickOutside(e);
    handleDashFilterClickOutside(e);
  }}
/>

<svelte:head>
  <title>Sales — Project Optima</title>
</svelte:head>

{#if !hasAccess}
  <AccessDenied
    message="You don't have permission to view Sales opportunities. Contact your administrator to request access."
  />
{:else}
  <div class="sales-page">
    <!-- Tab bar: only show when the user has access to more than one tab -->
    {#if canViewMine && canViewAll}
      <div class="sales-tab-row">
        <div class="sales-tab-bar">
          <button
            class="sales-tab"
            class:active={activeTab === "dashboard"}
            on:click={() => switchTab("dashboard")}
            type="button"
          >
            <svg
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              width="15"
              height="15"
            >
              <rect x="3" y="3" width="7" height="7" rx="1" />
              <rect x="14" y="3" width="7" height="7" rx="1" />
              <rect x="3" y="14" width="7" height="7" rx="1" />
              <rect x="14" y="14" width="7" height="7" rx="1" />
            </svg>
            My Dashboard
          </button>
          <button
            class="sales-tab"
            class:active={activeTab === "opportunities"}
            on:click={() => switchTab("opportunities")}
            type="button"
          >
            <svg
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              width="15"
              height="15"
            >
              <line x1="8" y1="6" x2="21" y2="6" />
              <line x1="8" y1="12" x2="21" y2="12" />
              <line x1="8" y1="18" x2="21" y2="18" />
              <line x1="3" y1="6" x2="3.01" y2="6" />
              <line x1="3" y1="12" x2="3.01" y2="12" />
              <line x1="3" y1="18" x2="3.01" y2="18" />
            </svg>
            All Opportunities
          </button>
        </div>
        {#if canCreate}
          <button
            class="sales-create-btn"
            on:click={() => (showCreateModal = true)}
            aria-label="Create opportunity"
          >
            <svg
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              width="15"
              height="15"
            >
              <line x1="12" y1="5" x2="12" y2="19" />
              <line x1="5" y1="12" x2="19" y2="12" />
            </svg>
            New Opportunity
          </button>
        {/if}
      </div>
    {/if}

    {#if (!canViewMine || !canViewAll) && canCreate}
      <div class="sales-tab-row sales-tab-row--solo">
        <button
          class="sales-create-btn"
          on:click={() => (showCreateModal = true)}
          aria-label="Create opportunity"
        >
          <svg
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            width="15"
            height="15"
          >
            <line x1="12" y1="5" x2="12" y2="19" />
            <line x1="5" y1="12" x2="19" y2="12" />
          </svg>
          New Opportunity
        </button>
      </div>
    {/if}

    {#if activeTab === "dashboard" && canViewMine}
      <!-- ── My Dashboard ── -->
      <div class="sales-dashboard">
        <div class="dash-body">
          <!-- Left sidebar: greeting + stats + financials -->
          <div class="dash-sidebar">
            <!-- Greeting -->
            <div class="dash-greeting">
              <h2 class="dash-title">
                {currentUser?.name ? currentUser.name.split(" ")[0] : "Welcome"}
              </h2>
              <p class="dash-subtitle">Your sales at a glance</p>
              <p class="dash-metrics-note">
                Overview data refreshes every 5 min
              </p>
            </div>

            <!-- Activity -->
            <div class="dash-metric-group">
              <div class="dash-metric-group-label">Activity</div>

              <!-- Open / Assigned summary row -->
              <div class="dash-activity-row">
                <div class="dash-activity-item">
                  <span class="dash-activity-number"
                    >{m?.openOpportunityCount ?? myOpenOpps.length}</span
                  >
                  <span class="dash-activity-label">Open</span>
                </div>
                <div class="dash-activity-divider"></div>
                <div class="dash-activity-item">
                  <span class="dash-activity-number"
                    >{m?.assignedOpportunityCount ?? opportunities.length}</span
                  >
                  <span class="dash-activity-label">Assigned</span>
                </div>
                <div class="dash-activity-divider"></div>
                <div class="dash-activity-item">
                  <span class="dash-activity-number"
                    >{m?.closedOpportunityCount?.mtd ?? 0}</span
                  >
                  <span class="dash-activity-label">Closed MTD</span>
                </div>
              </div>

              <!-- Win / Loss bar -->
              {#if (m?.winCount?.mtd ?? 0) + (m?.lossCount?.mtd ?? 0) > 0}
                {@const wins = m?.winCount?.mtd ?? 0}
                {@const losses = m?.lossCount?.mtd ?? 0}
                {@const total = wins + losses}
                {@const winPct = total > 0 ? (wins / total) * 100 : 0}
                <div class="dash-wl-card">
                  <div class="dash-wl-header">
                    <span class="dash-wl-won">
                      <span class="dash-wl-dot dash-wl-dot--won"></span>
                      {wins} Won
                    </span>
                    <span class="dash-wl-label">MTD</span>
                    <span class="dash-wl-lost">
                      {losses} Lost
                      <span class="dash-wl-dot dash-wl-dot--lost"></span>
                    </span>
                  </div>
                  <div class="dash-wl-bar">
                    <div class="dash-wl-bar-won" style="width: {winPct}%"></div>
                    <div
                      class="dash-wl-bar-lost"
                      style="width: {100 - winPct}%"
                    ></div>
                  </div>
                  <div class="dash-wl-footer">
                    <span class="dash-wl-rate"
                      >{winPct.toFixed(0)}% win rate</span
                    >
                    <span class="dash-wl-ytd"
                      >{m?.winCount?.ytd ?? 0}W / {m?.lossCount?.ytd ?? 0}L YTD</span
                    >
                  </div>
                </div>
              {:else}
                <div class="dash-wl-empty">No closed deals this month</div>
              {/if}
            </div>

            <!-- Financials -->
            <div class="dash-metric-group">
              <div class="dash-metric-group-label">Financials</div>

              <!-- Pipeline block -->
              <div class="dash-fin-block">
                <div class="dash-fin-kv">
                  <span class="dash-fin-kv-label">Pipeline</span>
                  <span class="dash-fin-kv-value" class:dash-ph={!m}
                    >{fmt$(m?.pipelineRevenue)}</span
                  >
                </div>
                {#if m}
                  {@const wPct =
                    m.pipelineRevenue > 0
                      ? (m.weightedPipelineRevenue / m.pipelineRevenue) * 100
                      : 0}
                  <div class="dash-fin-bar-row">
                    <div class="dash-fin-bar">
                      <div
                        class="dash-fin-bar-fill"
                        style="width: {Math.min(wPct, 100)}%"
                      ></div>
                    </div>
                    <span class="dash-fin-bar-label"
                      >{fmt$(m.weightedPipelineRevenue)} weighted</span
                    >
                  </div>
                {/if}
              </div>

              <!-- Closed revenue block -->
              <div class="dash-fin-block">
                <div class="dash-fin-kv">
                  <span class="dash-fin-kv-label">Closed MTD</span>
                  <span class="dash-fin-kv-value" class:dash-ph={!m}
                    >{fmt$(m?.closedWonRevenueMtd)}</span
                  >
                </div>
                <div class="dash-fin-kv dash-fin-kv--sub">
                  <span class="dash-fin-kv-label">Closed YTD</span>
                  <span class="dash-fin-kv-value" class:dash-ph={!m}
                    >{fmt$(m?.closedWonRevenueYtd)}</span
                  >
                </div>
              </div>
            </div>

            <!-- Performance -->
            <div class="dash-metric-group">
              <div class="dash-metric-group-label">Performance</div>

              <!-- Days to close + avg deal size inline -->
              <div class="dash-activity-row">
                <div class="dash-activity-item">
                  <span class="dash-activity-number" class:dash-ph={!m}
                    >{fmtDays(m?.avgDaysToClose)}</span
                  >
                  <span class="dash-activity-label">Avg Close</span>
                </div>
                <div class="dash-activity-divider"></div>
                <div class="dash-activity-item">
                  <span
                    class="dash-activity-number dash-stat-number--money"
                    class:dash-ph={!m}>{fmt$(m?.avgOpenDealSize)}</span
                  >
                  <span class="dash-activity-label">Avg Open</span>
                </div>
                <div class="dash-activity-divider"></div>
                <div class="dash-activity-item">
                  <span
                    class="dash-activity-number dash-stat-number--money"
                    class:dash-ph={!m}>{fmt$(m?.avgWonDealSize?.ytd)}</span
                  >
                  <span class="dash-activity-label">Avg Won</span>
                </div>
              </div>

              <!-- Win rate visual: MTD vs YTD -->
              <div class="dash-fin-block">
                <div class="dash-fin-kv">
                  <span class="dash-fin-kv-label">Win Rate MTD</span>
                  <span class="dash-fin-kv-value" class:dash-ph={!m}
                    >{fmtPct(m?.winRate?.mtd)}</span
                  >
                </div>
                {#if m}
                  <div class="dash-fin-bar-row">
                    <div class="dash-fin-bar dash-fin-bar--green">
                      <div
                        class="dash-fin-bar-fill"
                        style="width: {Math.min(
                          (m.winRate.mtd ?? 0) * 100,
                          100
                        )}%"
                      ></div>
                    </div>
                  </div>
                {/if}
                <div class="dash-fin-kv dash-fin-kv--sub">
                  <span class="dash-fin-kv-label">Win Rate YTD</span>
                  <span class="dash-fin-kv-value" class:dash-ph={!m}
                    >{fmtPct(m?.winRate?.ytd)}</span
                  >
                </div>
                {#if m}
                  <div class="dash-fin-bar-row">
                    <div class="dash-fin-bar dash-fin-bar--green">
                      <div
                        class="dash-fin-bar-fill"
                        style="width: {Math.min(
                          (m.winRate.ytd ?? 0) * 100,
                          100
                        )}%"
                      ></div>
                    </div>
                  </div>
                {/if}
              </div>
            </div>
          </div>

          <!-- Right main: table -->
          <div class="dash-main">
            <div class="dash-section">
              <div class="dash-section-header">
                <h3 class="dash-section-title">My Opportunities</h3>
                <div class="dash-section-actions">
                  <div class="dash-search-wrap">
                    <svg
                      class="dash-search-icon"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      width="14"
                      height="14"
                    >
                      <circle cx="11" cy="11" r="8" />
                      <line x1="21" y1="21" x2="16.65" y2="16.65" />
                    </svg>
                    <input
                      class="dash-search-input"
                      type="search"
                      placeholder="Search…"
                      bind:value={dashSearch}
                      on:keydown={handleDashSearchKeydown}
                    />
                  </div>
                  <div class="dash-filter-wrap">
                    <button
                      class="sales-filter-btn"
                      class:has-filters={dashHideClosed}
                      bind:this={dashFilterBtnEl}
                      on:click={toggleDashFilterPopover}
                      aria-label="Filters"
                      aria-expanded={dashFilterOpen}
                      type="button"
                    >
                      <svg
                        viewBox="0 0 24 24"
                        fill="none"
                        stroke="currentColor"
                        stroke-width="2"
                        width="13"
                        height="13"
                      >
                        <polygon
                          points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"
                        />
                      </svg>
                      Filters
                      {#if dashHideClosed}
                        <span class="sales-filter-badge">1</span>
                      {/if}
                    </button>
                    {#if dashFilterOpen}
                      <div
                        class="sales-filter-popover"
                        bind:this={dashFilterPopoverEl}
                      >
                        <label class="sales-filter-option">
                          <input
                            type="checkbox"
                            checked={!dashHideClosed}
                            on:change={() => {
                              const newVal = !dashHideClosed;
                              dashHideClosed = newVal;
                              dashFilterOpen = false;
                              console.log(
                                "[dash filter] hideClosed:",
                                newVal,
                                "navigating..."
                              );
                              navigateDashFilters(newVal);
                            }}
                          />
                          <span>Include closed opportunities</span>
                        </label>
                      </div>
                    {/if}
                  </div>
                  {#if canViewAll}
                    <button
                      class="dash-view-all-btn"
                      on:click={() => switchTab("opportunities")}
                      type="button"
                    >
                      View All →
                    </button>
                  {/if}
                </div>
              </div>

              {#if opportunities.length === 0 && !dashSearch && !data.dashIncludeClosed}
                <div class="dash-empty">
                  <NoResultsMonkey
                    message="No opportunities are currently assigned to you."
                  />
                </div>
              {:else if filteredMyOpportunities.length === 0}
                <div class="dash-empty">
                  <NoResultsMonkey
                    message="No opportunities match your search."
                  />
                </div>
              {:else}
                <div class="dash-table-wrap">
                  <table class="sales-table slim">
                    <thead>
                      <tr>
                        <th class="col-opportunity">Opportunity</th>
                        <th class="col-company">Company</th>
                        <th class="col-status">Status</th>
                        <th class="col-rating">Interest</th>
                        <th class="col-close">Expected Close</th>
                        <th class="col-updated">Updated</th>
                      </tr>
                    </thead>
                    <tbody>
                      {#each filteredMyOpportunities as opp (opp.id)}
                        <tr
                          class="sales-row"
                          class:closed-row={opp.closedFlag}
                          tabindex="0"
                          on:click={() =>
                            goto(`/sales/opportunity/${opp.id}?from=dashboard`)}
                          on:contextmenu={(e) => contextMenu.open(e, opp)}
                          on:keydown={(e) =>
                            handleRowKeydown(e, opp.id, "dashboard")}
                          style="cursor: pointer;"
                        >
                          <td class="col-opportunity">
                            <div class="sales-opportunity">
                              <span class="opp-name">{opp.name}</span>
                              {#if opp.cwOpportunityId}
                                <span class="opp-meta mono"
                                  >CW #{opp.cwOpportunityId}</span
                                >
                              {/if}
                            </div>
                          </td>
                          <td class="col-company">{companyLabel(opp)}</td>
                          <td class="col-status">
                            <span
                              class="sales-status-badge {statusColorClass(opp)}"
                              class:status-equiv={isEquivalencyStatus(opp)}
                            >
                              {statusLabel(opp)}
                            </span>
                          </td>
                          <td class="col-rating">
                            {#if opp.interest}
                              <span
                                class="sales-rating-badge {ratingHeatClass(
                                  opp.interest
                                )}"
                              >
                                <span class="sales-heat-dots">
                                  {#each [1, 2, 3] as level}
                                    <span
                                      style={getDotStyle(level, opp.interest)}
                                    ></span>
                                  {/each}
                                </span>
                                {opp.interest}
                              </span>
                            {:else}
                              —
                            {/if}
                          </td>
                          <td
                            class="col-close"
                            class:date-overdue={!opp.closedFlag &&
                              opp.expectedCloseDate &&
                              new Date(opp.expectedCloseDate) < new Date()}
                            >{formatDate(opp.expectedCloseDate)}</td
                          >
                          <td class="col-updated"
                            >{formatDate(
                              opp.cwLastUpdated || opp.updatedAt
                            )}</td
                          >
                        </tr>
                      {/each}
                    </tbody>
                  </table>
                </div>
              {/if}
            </div>
          </div>
        </div>
      </div>
    {:else if activeTab === "opportunities" && canViewAll}
      <!-- ── All Opportunities ── -->
      <div class="sales-pane">
        <div class="sales-header">
          <div class="sales-header-left">
            <h2 class="sales-title">Sales Opportunities</h2>
            {#if totalRecords > 0}
              <span class="sales-result-count">
                {totalRecords} record{totalRecords === 1 ? "" : "s"}
              </span>
            {/if}
          </div>
          <div class="sales-header-actions">
            <div class="sales-search-bar">
              <svg
                class="sales-search-icon"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
              >
                <circle cx="11" cy="11" r="8" />
                <path d="M21 21l-4.35-4.35" />
              </svg>
              <input
                type="text"
                placeholder="Search opportunities…"
                bind:this={searchInputEl}
                bind:value={searchInput}
                on:input={handleSearch}
                on:keydown={handleKeydown}
              />
              {#if searchInput}
                <button
                  class="sales-search-clear"
                  on:click={() => {
                    searchInput = "";
                    handleSearch();
                  }}
                  aria-label="Clear search"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    width="14"
                    height="14"
                  >
                    <path d="M18 6L6 18M6 6l12 12" />
                  </svg>
                </button>
              {/if}
            </div>

            <div class="sales-filter-wrap">
              <button
                class="sales-filter-btn"
                class:has-filters={activeFilterCount > 0}
                bind:this={filterBtnEl}
                on:click={toggleFilterPopover}
                aria-label="Filters"
                aria-expanded={filterOpen}
              >
                <svg
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                  width="15"
                  height="15"
                >
                  <polygon
                    points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"
                  />
                </svg>
                Filters
                {#if activeFilterCount > 0}
                  <span class="sales-filter-badge">{activeFilterCount}</span>
                {/if}
              </button>

              {#if filterOpen}
                <div class="sales-filter-popover" bind:this={filterPopoverEl}>
                  <label class="sales-filter-option">
                    <input
                      type="checkbox"
                      checked={showClosed}
                      on:change={toggleClosed}
                    />
                    <span>Include closed opportunities</span>
                  </label>
                </div>
              {/if}
            </div>
          </div>
        </div>

        <div class="sales-body">
          <div class="sales-table-wrap">
            {#if opportunities.length === 0}
              <div class="sales-empty">
                <NoResultsMonkey
                  message={searchInput
                    ? "No opportunities match your search"
                    : "No opportunities found"}
                />
              </div>
            {:else}
              <table class="sales-table">
                <thead>
                  <tr>
                    <th class="col-opportunity">Opportunity</th>
                    <th class="col-company">Company</th>
                    <th class="col-status">Status</th>
                    <th class="col-rating">Interest</th>
                    <th class="col-owner">Owner</th>
                    <th class="col-close">Expected Close</th>
                    <th class="col-updated">Updated</th>
                  </tr>
                </thead>
                <tbody>
                  {#each opportunities as opp (opp.id)}
                    <tr
                      class="sales-row"
                      class:closed-row={opp.closedFlag}
                      tabindex="0"
                      on:click={() =>
                        goto(`/sales/opportunity/${opp.id}?from=opportunities`)}
                      on:contextmenu={(e) => contextMenu.open(e, opp)}
                      on:keydown={(e) =>
                        handleRowKeydown(e, opp.id, "opportunities")}
                      style="cursor: pointer;"
                    >
                      <td class="col-opportunity">
                        <div class="sales-opportunity">
                          <span class="opp-name">{opp.name}</span>
                          {#if opp.cwOpportunityId}
                            <span class="opp-meta mono"
                              >CW #{opp.cwOpportunityId}</span
                            >
                          {/if}
                        </div>
                      </td>
                      <td class="col-company">{companyLabel(opp)}</td>
                      <td class="col-status">
                        <span
                          class="sales-status-badge {statusColorClass(opp)}"
                          class:status-equiv={isEquivalencyStatus(opp)}
                          data-tooltip={isEquivalencyStatus(opp)
                            ? `Original: ${originalStatusName(opp)}`
                            : undefined}
                        >
                          {statusLabel(opp)}
                        </span>
                      </td>
                      <td class="col-rating">
                        {#if opp.interest}
                          <span
                            class="sales-rating-badge {ratingHeatClass(
                              opp.interest
                            )}"
                          >
                            <span class="sales-heat-dots">
                              {#each [1, 2, 3] as level}
                                <span style={getDotStyle(level, opp.interest)}
                                ></span>
                              {/each}
                            </span>
                            {opp.interest}
                          </span>
                        {:else}
                          —
                        {/if}
                      </td>
                      <td class="col-owner">{ownerLabel(opp)}</td>
                      <td
                        class="col-close"
                        class:date-overdue={!opp.closedFlag &&
                          opp.expectedCloseDate &&
                          new Date(opp.expectedCloseDate) < new Date()}
                      >
                        {formatDate(opp.expectedCloseDate)}
                      </td>
                      <td class="col-updated">
                        {formatDate(opp.cwLastUpdated || opp.updatedAt)}
                      </td>
                    </tr>
                  {/each}
                </tbody>
              </table>
            {/if}
          </div>
        </div>

        {#if totalPages > 1}
          <div class="sales-footer">
            <span class="sales-page-info">
              Page {currentPage} of {totalPages}
            </span>
            <Pagination
              {currentPage}
              {totalPages}
              onNavigate={navigateToPage}
            />
          </div>
        {/if}
      </div>
    {/if}
  </div>
{/if}

<CreateOpportunityModal
  bind:isOpen={showCreateModal}
  onSuccess={() => invalidateAll()}
  opportunityTypes={data.opportunityTypes ?? []}
/>

<OpportunityContextMenu
  bind:this={contextMenu}
  permissions={data.permissions}
  on:workflowChanged={() => invalidateAll()}
/>

<style>
  .sales-create-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 34px;
    padding: 0 15px;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 550;
    cursor: pointer;
    background: linear-gradient(135deg, #3b82f6 0%, #6366f1 100%);
    border: 1px solid transparent;
    color: #fff;
    transition: all 0.15s;
    box-shadow: 0 1px 4px -1px rgba(59, 130, 246, 0.3);
    white-space: nowrap;
  }

  .sales-create-btn:hover {
    filter: brightness(1.08);
    box-shadow: 0 3px 10px -2px rgba(59, 130, 246, 0.35);
    transform: translateY(-0.5px);
  }

  .sales-create-btn:active {
    transform: translateY(0);
  }
</style>
