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

  let contextMenu: OpportunityContextMenu;

  export let data: {
    permissions: PermissionMap;
    opportunities: SalesOpportunity[];
    opportunityTypes: OpportunityType[];
    totalPages: number;
    currentPage: number;
    totalRecords: number;
    search: string;
    includeClosed: boolean;
  };

  $: hasAccess = data.permissions["sales.opportunity.fetch.many"] === true;
  $: canCreate = data.permissions["sales.opportunity.create"] === true;

  let showCreateModal = false;

  // Build lookup maps for opportunity type resolution
  // directMap: type id → OpportunityType (exact match)
  // equivMap:  type id → OpportunityType (matched via optimaEquivalency)
  $: directMap = new Map<number, OpportunityType>(
    data.opportunityTypes.map((t) => [t.id, t])
  );
  $: equivMap = (() => {
    const m = new Map<number, OpportunityType>();
    for (const t of data.opportunityTypes) {
      if (t.optimaEquivalency) {
        for (const eqId of t.optimaEquivalency) {
          m.set(eqId, t);
        }
      }
    }
    return m;
  })();

  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;

  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}`);
        }, 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/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 });
    }
  }

  function statusLabel(op: SalesOpportunity): string {
    if (op.closedFlag) return "Closed";
    const statusId = op.status?.id;
    if (statusId != null) {
      if (directMap.has(statusId)) {
        return directMap.get(statusId)!.name;
      }
      if (equivMap.has(statusId)) {
        return equivMap.get(statusId)!.name + " *";
      }
      // Debug: log unmatched status IDs so we can see what's not resolving
      console.log("[Status Debug] Unmatched status", {
        oppName: op.name,
        statusId,
        statusName: op.status?.name,
        directMapKeys: [...directMap.keys()],
        equivMapKeys: [...equivMap.keys()],
      });
    }
    return op.status?.name || "Open";
  }

  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={handleFilterClickOutside} />

<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">
    <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>

          {#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 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}
                    on:click={() => goto(`/sales/opportunity/${opp.id}`)}
                    on:contextmenu={(e) => contextMenu.open(e, opp)}
                    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">
                      {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>
  </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;
    padding: 7px 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>
