<script lang="ts">
  import { onMount } from 'svelte';
  import { page } from '$app/state';
  import ImmichPicker from '$lib/components/shared/ImmichPicker.svelte';

  // ── Types matching NocoDB fields ──
  interface InventoryItem {
    id: number;
    name: string;
    order: string;
    sku: string;
    serial: string;
    status: string;
    price: number;
    tax: number;
    total: number;
    qty: number;
    tracking: string;
    vendor: string;
    buyerName: string;
    date: string;
    notes: string;
    photos: number;
    photoUrls: string[];
  }

  interface ItemDetailRaw {
    Id: number;
    Item: string;
    'Order Number': string;
    'Serial Numbers': string;
    SKU: string;
    Received: string;
    'Price Per Item': number;
    Tax: number;
    Total: number;
    QTY: number;
    'Tracking Number': string;
    Source: string;
    Name: string;
    Date: string;
    Notes: string;
    photos: any[];
    [key: string]: any;
  }

  // ── State ──
  let activeTab = $state<'issues' | 'review' | 'all'>('issues');
  let searchQuery = $state('');
  let detailOpen = $state(false);
  let selectedItem = $state<InventoryItem | null>(null);
  let selectedDetail = $state<ItemDetailRaw | null>(null);
  let nocodbUrl = $state('');

  let recentItems = $state<InventoryItem[]>([]);
  let issueItems = $state<InventoryItem[]>([]);
  let reviewItems = $state<InventoryItem[]>([]);
  let recentLoaded = $state(false);
  let loading = $state(true);
  let searching = $state(false);
  let searchResults = $state<InventoryItem[] | null>(null);
  let saving = $state(false);
  let debounceTimer: ReturnType<typeof setTimeout>;

  // ── Derived ──
  const issueCount = $derived(issueItems.length);
  const reviewCount = $derived(reviewItems.length);

  const displayedItems = $derived(() => {
    if (searchResults !== null) return searchResults;
    if (activeTab === 'issues') return issueItems;
    if (activeTab === 'review') return reviewItems;
    return recentItems;
  });

  // ── Map API response to our item shape ──
  function mapIssue(raw: any): InventoryItem {
    return {
      id: raw.id,
      name: raw.item || '',
      order: raw.orderNumber || '',
      sku: raw.sku || '',
      serial: raw.serialNumbers || '',
      status: normalizeStatus(raw.received || ''),
      price: 0,
      tax: 0,
      total: 0,
      qty: 1,
      tracking: raw.trackingNumber || '',
      vendor: '',
      buyerName: '',
      date: '',
      notes: raw.notes || '',
      photos: 0,
      photoUrls: []
    };
  }

  const NOCODB_BASE = 'https://noco.quadjourney.com';

  function extractPhotoUrls(photos: any[]): string[] {
    if (!Array.isArray(photos)) return [];
    return photos
      .filter((p: any) => p && p.signedPath)
      .map((p: any) => `${NOCODB_BASE}/${p.signedPath}`);
  }

  function mapDetail(raw: ItemDetailRaw): InventoryItem {
    const photoUrls = extractPhotoUrls(raw.photos);
    return {
      id: raw.Id,
      name: raw.Item || '',
      order: raw['Order Number'] || '',
      sku: raw.SKU || '',
      serial: raw['Serial Numbers'] || '',
      status: normalizeStatus(raw.Received || ''),
      price: raw['Price Per Item'] || 0,
      tax: raw.Tax || 0,
      total: raw.Total || 0,
      qty: raw.QTY || 1,
      tracking: raw['Tracking Number'] || '',
      vendor: raw.Source || '',
      buyerName: raw.Name || '',
      date: raw.Date || '',
      notes: raw.Notes || '',
      photos: Array.isArray(raw.photos) ? raw.photos.length : 0,
      photoUrls
    };
  }

  function normalizeStatus(received: string): string {
    if (!received) return 'Pending';
    const lower = received.toLowerCase();
    if (lower === 'issue' || lower === 'issues') return 'Issue';
    if (lower === 'needs review') return 'Needs Review';
    if (lower === 'pending') return 'Pending';
    if (lower === 'closed') return 'Closed';
    // Any date string or other value = Received
    return 'Received';
  }

  // ── API calls ──
  async function loadSummary() {
    try {
      const res = await fetch('/api/inventory/summary', { credentials: 'include' });
      if (res.ok) {
        const data = await res.json();
        issueItems = (data.issues || []).map(mapIssue);
        reviewItems = (data.needsReview || []).map(mapIssue);
      }
    } catch { /* silent */ }
  }

  function mapSearchResult(r: any): InventoryItem {
    return {
      id: r.id,
      name: r.item || '',
      order: '', sku: '', serial: '',
      status: normalizeStatus(r.received || ''),
      price: 0, tax: 0, total: 0, qty: 1,
      tracking: '', vendor: '', buyerName: '', date: '',
      notes: '', photos: 0, photoUrls: []
    };
  }

  async function loadRecent() {
    if (recentLoaded) return;
    try {
      const res = await fetch('/api/inventory/recent?limit=30', { credentials: 'include' });
      if (res.ok) {
        const data = await res.json();
        recentItems = (data.items || []).map(mapSearchResult);
        recentLoaded = true;
      }
    } catch { /* silent */ }
  }

  async function searchItems(query: string) {
    if (!query.trim()) { searchResults = null; return; }
    searching = true;
    try {
      const res = await fetch(`/api/inventory/search-records?q=${encodeURIComponent(query)}`, { credentials: 'include' });
      if (res.ok) {
        const data = await res.json();
        searchResults = (data.results || []).map((r: any) => ({
          id: r.id,
          name: r.item || '',
          order: '', sku: '', serial: '',
          status: normalizeStatus(r.received || ''),
          price: 0, tax: 0, total: 0, qty: 1,
          tracking: '', vendor: '', buyerName: '', date: '',
          notes: '', photos: 0
        }));
      }
    } catch { searchResults = []; }
    finally { searching = false; }
  }

  async function loadItemDetail(id: number) {
    try {
      const res = await fetch(`/api/inventory/item-details/${id}`, { credentials: 'include' });
      if (res.ok) {
        const data = await res.json();
        selectedDetail = data.item;
        selectedItem = mapDetail(data.item);
        nocodbUrl = data.nocodb_url || '';
        detailOpen = true;
      }
    } catch { /* silent */ }
  }

  async function updateField(field: string, value: string | number) {
    if (!selectedItem) return;
    saving = true;
    try {
      const res = await fetch(`/api/inventory/item/${selectedItem.id}`, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ [field]: value }),
        credentials: 'include'
      });
      if (res.ok && selectedDetail) {
        (selectedDetail as any)[field] = value;
        selectedItem = mapDetail(selectedDetail);
        // Update in lists
        updateItemInLists(selectedItem);
      }
    } catch { /* silent */ }
    finally { saving = false; }
  }

  function updateItemInLists(item: InventoryItem) {
    const issueIdx = issueItems.findIndex(i => i.id === item.id);
    const allIdx = allItems.findIndex(i => i.id === item.id);
    if (allIdx >= 0) allItems[allIdx] = item;
    // Add/remove from issues based on status
    if (item.status === 'Issue') {
      if (issueIdx < 0) issueItems = [...issueItems, item];
      else issueItems[issueIdx] = item;
    } else {
      if (issueIdx >= 0) issueItems = issueItems.filter(i => i.id !== item.id);
    }
  }

  // ── Event handlers ──
  function onSearchInput() {
    clearTimeout(debounceTimer);
    if (!searchQuery.trim()) { searchResults = null; return; }
    debounceTimer = setTimeout(() => searchItems(searchQuery), 300);
  }

  function openDetail(item: InventoryItem) {
    loadItemDetail(item.id);
  }

  function closeDetail() {
    detailOpen = false;
    selectedItem = null;
    selectedDetail = null;
  }

  const statusOptions = ['Issue', 'Needs Review', 'Pending', 'Received', 'Closed'];

  // Maps our status to NocoDB "Received" field values
  function statusToReceived(status: string): string {
    if (status === 'Issue') return 'Issues';
    if (status === 'Needs Review') return 'Needs Review';
    if (status === 'Pending') return 'Pending';
    if (status === 'Closed') return 'Closed';
    // For "Received", we set today's date
    return new Date().toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
  }

  async function changeStatus(newStatus: string) {
    if (!selectedItem) return;
    const receivedValue = statusToReceived(newStatus);
    await updateField('Received', receivedValue);
  }

  function statusColor(status: string) {
    if (status === 'Issue' || status === 'Issues') return 'error';
    if (status === 'Needs Review') return 'warning';
    if (status === 'Received') return 'success';
    if (status === 'Pending') return 'warning';
    if (status === 'Closed') return 'muted';
    return 'muted';
  }

  function formatPrice(n: number) {
    return '$' + n.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  }

  // ── Inline editing ──
  let editingField = $state('');
  let editValue = $state('');

  // NocoDB field name → our display label + item property
  const editableFields: Record<string, { nocoField: string; type: 'text' | 'number' }> = {
    'Item': { nocoField: 'Item', type: 'text' },
    'Price Per Item': { nocoField: 'Price Per Item', type: 'number' },
    'Tax': { nocoField: 'Tax', type: 'number' },
    'Total': { nocoField: 'Total', type: 'number' },
    'QTY': { nocoField: 'QTY', type: 'number' },
    'SKU': { nocoField: 'SKU', type: 'text' },
    'Serial Numbers': { nocoField: 'Serial Numbers', type: 'text' },
    'Order Number': { nocoField: 'Order Number', type: 'text' },
    'Source': { nocoField: 'Source', type: 'text' },
    'Name': { nocoField: 'Name', type: 'text' },
    'Date': { nocoField: 'Date', type: 'text' },
    'Tracking Number': { nocoField: 'Tracking Number', type: 'text' },
    'Notes': { nocoField: 'Notes', type: 'text' },
  };

  function startEdit(nocoField: string, currentValue: any) {
    editingField = nocoField;
    editValue = currentValue != null ? String(currentValue) : '';
  }

  async function saveEdit() {
    if (!editingField || !selectedItem) return;
    const field = editableFields[editingField];
    const value = field?.type === 'number' ? Number(editValue) || 0 : editValue;
    await updateField(editingField, value);
    editingField = '';
    editValue = '';
  }

  function cancelEdit() {
    editingField = '';
    editValue = '';
  }

  function handleEditKeydown(e: KeyboardEvent) {
    if (e.key === 'Enter') saveEdit();
    if (e.key === 'Escape') cancelEdit();
  }

  // Get raw NocoDB value for a field
  function rawField(field: string): any {
    return selectedDetail ? (selectedDetail as any)[field] : '';
  }

  // ── Action handlers ──
  async function duplicateItem() {
    if (!selectedItem) return;
    saving = true;
    try {
      const res = await fetch(`/api/inventory/duplicate/${selectedItem.id}`, {
        method: 'POST', credentials: 'include'
      });
      if (res.ok) {
        const data = await res.json();
        const newId = data.newId || data.id;
        if (newId) loadItemDetail(newId);
      }
    } catch { /* silent */ }
    finally { saving = false; }
  }

  async function sendToPhone() {
    if (!selectedItem) return;
    saving = true;
    try {
      await fetch('/api/inventory/send-to-phone', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ rowId: selectedItem.id }),
        credentials: 'include'
      });
    } catch { /* silent */ }
    finally { saving = false; }
  }

  // ── Photo upload ──
  let fileInput: HTMLInputElement;
  let uploading = $state(false);
  let uploadMenuOpen = $state(false);

  function triggerUpload() {
    fileInput?.click();
  }

  async function handleFileSelect(e: Event) {
    const input = e.target as HTMLInputElement;
    if (!input.files?.length || !selectedItem) return;
    uploading = true;
    try {
      const formData = new FormData();
      formData.append('rowId', String(selectedItem.id));
      for (const file of input.files) {
        formData.append('photos', file);
      }
      const res = await fetch('/api/inventory/upload', {
        method: 'POST',
        body: formData,
        credentials: 'include'
      });
      if (res.ok) {
        // Reload item to get updated photos
        loadItemDetail(selectedItem.id);
      }
    } catch { /* silent */ }
    finally {
      uploading = false;
      input.value = '';
    }
  }

  // ── Immich picker ──
  let immichOpen = $state(false);

  async function handleImmichSelect(assetIds: string[]) {
    if (!selectedItem || !assetIds.length) return;
    uploading = true;
    try {
      // Server-to-server: inventory service downloads from Immich and uploads to NocoDB
      const res = await fetch('/api/inventory/upload-from-immich', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
        body: JSON.stringify({
          rowId: selectedItem.id,
          assetIds,
          deleteAfter: true
        })
      });
      if (res.ok) {
        const data = await res.json();
        console.log(`Uploaded ${data.uploadedCount} photos, deleted ${data.deletedCount} from Immich`);
      }
      // Reload to show new photos
      loadItemDetail(selectedItem.id);
    } catch { /* silent */ }
    finally { uploading = false; }
  }

  async function createNewItem() {
    saving = true;
    try {
      const res = await fetch('/api/inventory/create', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ Item: 'New Item' }),
        credentials: 'include'
      });
      if (res.ok) {
        const data = await res.json();
        if (data.id) loadItemDetail(data.id);
      }
    } catch { /* silent */ }
    finally { saving = false; }
  }

  // ── Init ──
  onMount(async () => {
    await loadSummary();
    loading = false;

    // Auto-open from query param
    const itemId = page.url.searchParams.get('item');
    if (itemId) loadItemDetail(Number(itemId));
  });
</script>

{#snippet editableRow(nocoField: string, displayValue: string, classes: string)}
  {#if editingField === nocoField}
    <div class="detail-row editing">
      <span class="field-label">{nocoField}</span>
      <input
        class="edit-input {classes}"
        type={editableFields[nocoField]?.type === 'number' ? 'number' : 'text'}
        bind:value={editValue}
        onkeydown={handleEditKeydown}
        onblur={saveEdit}
        autofocus
      />
    </div>
  {:else}
    <!-- svelte-ignore a11y_no_static_element_interactions -->
    <div class="detail-row editable" onclick={() => startEdit(nocoField, rawField(nocoField))}>
      <span class="field-label">{nocoField}</span>
      <span class="field-value {classes}">{displayValue}</span>
    </div>
  {/if}
{/snippet}

<div class="page">
  <div class="app-surface">
    <div class="page-header">
      <div class="header-row">
        <div>
          <div class="page-title">INVENTORY</div>
          <div class="page-subtitle">{loading ? 'Loading...' : ''}<strong>{issueCount} issues</strong> · {reviewCount} needs review</div>
        </div>
        <button class="btn-primary" onclick={createNewItem}>+ New Item</button>
      </div>
    </div>

    <!-- Search -->
    <div class="search-wrap">
      <svg class="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"
        class="search-input"
        placeholder="Search by item name, order number, serial number, SKU..."
        bind:value={searchQuery}
        oninput={onSearchInput}
      />
      {#if searchQuery}
        <button class="search-clear" onclick={() => { searchQuery = ''; searchResults = null; }}>
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
        </button>
      {/if}
    </div>

    <!-- Tabs (hidden during search) -->
    {#if !searchQuery && searchResults === null}
      <div class="tabs">
        <button class="tab" class:active={activeTab === 'issues'} onclick={() => activeTab = 'issues'}>
          Issues <span class="tab-badge">{issueCount}</span>
        </button>
        <button class="tab" class:active={activeTab === 'review'} onclick={() => activeTab = 'review'}>
          Needs Review <span class="tab-badge review">{reviewCount}</span>
        </button>
        <button class="tab" class:active={activeTab === 'all'} onclick={() => { activeTab = 'all'; loadRecent(); }}>
          Recent
        </button>
      </div>
    {:else}
      <div class="search-results-label">{displayedItems().length} result{displayedItems().length !== 1 ? 's' : ''} for "{searchQuery}"</div>
    {/if}

    <!-- Item rows -->
    <div class="items-card">
      {#each displayedItems() as item (item.id)}
        <button class="item-row" class:has-issue={item.status === 'Issue'} class:has-review={item.status === 'Needs Review'} onclick={() => openDetail(item)}>
          <div class="item-info">
            <div class="item-name">{item.name}</div>
            <div class="item-meta">Order #{item.order} · SKU: {item.sku}</div>
          </div>
          <span class="status-badge {statusColor(item.status)}">{item.status}</span>
          <svg class="row-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18l6-6-6-6"/></svg>
        </button>
      {/each}
      {#if displayedItems().length === 0}
        <div class="empty">No items found</div>
      {/if}
    </div>
  </div>
</div>

<!-- Detail sheet/modal -->
{#if detailOpen && selectedItem}
  <!-- svelte-ignore a11y_no_static_element_interactions -->
  <div class="detail-overlay" onclick={closeDetail}>
    <!-- svelte-ignore a11y_no_static_element_interactions -->
    <div class="detail-sheet" onclick={(e) => e.stopPropagation()}>
      <!-- 1. Title (editable) -->
      <div class="detail-header">
        {#if editingField === 'Item'}
          <input
            class="edit-input detail-title-edit"
            type="text"
            bind:value={editValue}
            onkeydown={handleEditKeydown}
            onblur={saveEdit}
            autofocus
          />
        {:else}
          <!-- svelte-ignore a11y_no_static_element_interactions -->
          <div class="detail-title editable" onclick={() => startEdit('Item', rawField('Item'))}>{selectedItem.name}</div>
        {/if}
        <button class="detail-close" onclick={closeDetail}>
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
        </button>
      </div>

      <!-- 2. Status control (segmented) -->
      <div class="status-control">
        {#each statusOptions as status}
          <button
            class="status-seg"
            class:active={selectedItem.status === status}
            data-status={status}
            onclick={() => changeStatus(status)}
          >
            {status}
          </button>
        {/each}
      </div>

      <!-- 3. Photos -->
      <div class="detail-photos">
        {#if selectedItem.photoUrls.length > 0}
          {#each selectedItem.photoUrls as url}
            <img class="photo-img" src={url} alt="Item photo" loading="lazy" />
          {/each}
        {:else}
          <div class="photo-placeholder empty-photo">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="M21 15l-5-5L5 21"/></svg>
            <span>No photos yet</span>
          </div>
        {/if}
      </div>

      <!-- 4. Actions -->
      <div class="actions-group">
        <div class="actions-row">
          <input type="file" accept="image/*" multiple class="hidden-input" bind:this={fileInput} onchange={handleFileSelect} />
          <button class="action-btn primary" onclick={() => uploadMenuOpen = !uploadMenuOpen} disabled={uploading}>
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg>
            {uploading ? 'Uploading...' : 'Upload Photos'}
          </button>
          {#if uploadMenuOpen}
            <div class="upload-menu">
              <button class="upload-option" onclick={() => { uploadMenuOpen = false; triggerUpload(); }}>
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
                From device
              </button>
              <button class="upload-option" onclick={() => { uploadMenuOpen = false; immichOpen = true; }}>
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="M21 15l-5-5L5 21"/></svg>
                From Immich
              </button>
            </div>
          {/if}
          <button class="action-btn" onclick={sendToPhone}>
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="5" y="2" width="14" height="20" rx="2"/><line x1="12" y1="18" x2="12.01" y2="18"/></svg>
            Phone
          </button>
        </div>
        <div class="actions-row secondary">
          <button class="action-btn sm" onclick={duplicateItem}>
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
            Duplicate
          </button>
          <a class="action-btn sm ghost" href={nocodbUrl || '#'} target="_blank" rel="noopener">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>
            NocoDB
          </a>
        </div>
      </div>

      <!-- Purchase -->
      <div class="section-group">
        <div class="section-label">Purchase</div>
        <div class="detail-fields">
          {@render editableRow('Price Per Item', formatPrice(selectedItem.price), 'mono')}
          {@render editableRow('Tax', formatPrice(selectedItem.tax), 'mono')}
          {@render editableRow('Total', formatPrice(selectedItem.total), 'mono strong')}
          {@render editableRow('QTY', String(selectedItem.qty), '')}
        </div>
      </div>

      <!-- Item Info -->
      <div class="section-group">
        <div class="section-label">Item Info</div>
        <div class="detail-fields">
          {@render editableRow('SKU', selectedItem.sku || '—', 'mono')}
          {@render editableRow('Serial Numbers', selectedItem.serial || '—', 'mono')}
        </div>
      </div>

      <!-- Order -->
      <div class="section-group">
        <div class="section-label">Order</div>
        <div class="detail-fields">
          {@render editableRow('Order Number', selectedItem.order || '—', 'mono')}
          {@render editableRow('Source', selectedItem.vendor || '—', '')}
          {@render editableRow('Name', selectedItem.buyerName || '—', '')}
          {@render editableRow('Date', selectedItem.date || '—', '')}
        </div>
      </div>

      <!-- Shipping -->
      <div class="section-group">
        <div class="section-label">Shipping</div>
        <div class="detail-fields">
          {@render editableRow('Tracking Number', selectedItem.tracking || '—', 'mono')}
        </div>
      </div>

      <!-- Notes -->
      <div class="section-group">
        <div class="section-label">Notes</div>
        <div class="detail-fields">
          {#if editingField === 'Notes'}
            <div class="detail-row">
              <textarea
                class="edit-input edit-textarea"
                bind:value={editValue}
                onkeydown={handleEditKeydown}
                onblur={saveEdit}
                rows="3"
              ></textarea>
            </div>
          {:else}
            <!-- svelte-ignore a11y_no_static_element_interactions -->
            <div class="detail-row editable" onclick={() => startEdit('Notes', rawField('Notes'))}>
              <span class="field-value" style="text-align:left;font-weight:400;color:var(--text-2);width:100%">{selectedItem.notes || 'Add notes...'}</span>
            </div>
          {/if}
        </div>
      </div>
    </div>
  </div>
{/if}

{#if immichOpen}
  <ImmichPicker bind:open={immichOpen} onselect={handleImmichSelect} />
{/if}

<style>
  .header-row { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-4); }
  .page-subtitle { font-size: var(--text-2xl); font-weight: 300; color: var(--text-1); line-height: 1.2; }
  .btn-primary { padding: var(--sp-2) var(--sp-4); border-radius: var(--radius-md); background: var(--accent); color: white; border: none; font-size: var(--text-sm); font-weight: 600; cursor: pointer; font-family: var(--font); transition: opacity var(--transition); }
  .btn-primary:hover { opacity: 0.9; }

  /* ── Search ── */
  .search-wrap { position: relative; margin-bottom: var(--sp-4); }
  .search-icon { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); width: 18px; height: 18px; color: var(--text-4); pointer-events: none; transition: color var(--transition); }
  .search-input { width: 100%; padding: var(--sp-3) var(--sp-10) var(--sp-3) 42px; border-radius: var(--radius); border: 1.5px solid var(--border); background: var(--card); color: var(--text-1); font-size: var(--text-md); font-family: var(--font); transition: all var(--transition); box-shadow: var(--shadow-xs); }
  .search-input::placeholder { color: var(--text-4); }
  .search-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-dim), var(--shadow-sm); }
  .search-input:focus ~ .search-icon { color: var(--accent); }
  .search-clear { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); background: none; border: none; cursor: pointer; color: var(--text-4); padding: var(--sp-1); border-radius: var(--radius-xs); }
  .search-clear:hover { color: var(--text-2); background: var(--card-hover); }
  .search-clear svg { width: 16px; height: 16px; }
  .search-results-label { font-size: var(--text-sm); color: var(--text-3); margin-bottom: var(--sp-3); }

  /* ── Tabs ── */
  .tabs { display: flex; gap: var(--sp-1); margin-bottom: var(--sp-4); }
  .tab { padding: var(--sp-2) 14px; border-radius: var(--radius-md); font-size: var(--text-base); font-weight: 500; color: var(--text-3); background: none; border: none; cursor: pointer; transition: all var(--transition); font-family: var(--font); display: flex; align-items: center; gap: var(--sp-1.5); }
  .tab:hover { color: var(--text-1); background: var(--card-hover); }
  .tab.active { color: var(--text-1); background: var(--card); box-shadow: var(--shadow-xs); }
  .tab-badge { font-size: var(--text-xs); font-weight: 600; background: var(--error); color: white; padding: 1px 7px; border-radius: 10px; }
  .tab-badge.review { background: var(--warning); }
  .tab-count { font-size: var(--text-xs); color: var(--text-4); }

  /* ── Item rows ── */
  .items-card { background: var(--card); border-radius: var(--radius); border: 1px solid var(--border); box-shadow: var(--shadow-md); overflow: hidden; }
  .item-row { display: flex; align-items: center; gap: 14px; padding: 15px 16px; width: 100%; background: none; border: none; cursor: pointer; transition: background var(--transition); text-align: left; font-family: var(--font); color: inherit; }
  .item-row:hover { background: var(--card-hover); }
  .item-row + .item-row { border-top: 1px solid var(--border); }
  .item-row:nth-child(even) { background: color-mix(in srgb, var(--surface) 68%, var(--card)); }
  .item-row:nth-child(even):hover { background: var(--card-hover); }
  .item-row.has-issue { border-left: 4px solid var(--error); }
  .item-row.has-review { border-left: 4px solid var(--warning); }
  .item-info { flex: 1; min-width: 0; }
  .item-name { font-size: var(--text-base); font-weight: 600; color: var(--text-1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .item-meta { font-size: var(--text-sm); color: var(--text-2); margin-top: 3px; letter-spacing: 0.01em; }

  .status-badge { font-size: var(--text-xs); font-weight: 500; padding: 3px 10px; border-radius: var(--radius-sm); flex-shrink: 0; }
  .status-badge.error { background: var(--error-dim); color: var(--error); }
  .status-badge.success { background: var(--success-dim); color: var(--success); }
  .status-badge.warning { background: var(--warning-bg); color: var(--warning); }
  .status-badge.muted { background: var(--card-hover); color: var(--text-4); }

  .row-chevron { width: 14px; height: 14px; color: var(--text-4); flex-shrink: 0; opacity: 0.5; }
  .item-row:hover .row-chevron { opacity: 1; }
  .empty { padding: var(--sp-12); text-align: center; color: var(--text-3); font-size: var(--text-base); }

  /* ── Detail sheet ── */
  .detail-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.35); z-index: 60; display: flex; justify-content: flex-end; animation: fadeIn 150ms ease; }
  @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
  .detail-sheet { width: 520px; max-width: 100%; height: 100%; background: var(--surface); overflow-y: auto; padding: var(--sp-7); box-shadow: -12px 0 40px rgba(0,0,0,0.12); animation: slideIn 200ms ease; }
  @keyframes slideIn { from { transform: translateX(100%); } to { transform: translateX(0); } }

  .detail-header { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--sp-3); margin-bottom: 18px; }
  .detail-title { font-size: var(--text-lg); font-weight: 600; color: var(--text-1); line-height: 1.35; flex: 1; min-width: 0; }

  /* ── Status segmented control ── */
  .status-control {
    display: flex;
    justify-content: center;
    gap: 0;
    margin: 0 8px 22px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 3px;
    box-shadow: 0 1px 4px rgba(0,0,0,0.04);
  }
  .status-seg {
    flex: 1;
    padding: 8px 0;
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--text-3);
    background: none;
    border: none;
    border-radius: 9px;
    cursor: pointer;
    font-family: var(--font);
    transition: all var(--transition);
    text-align: center;
  }
  .status-seg:hover { color: var(--text-2); }
  .status-seg.active { color: var(--text-1); box-shadow: 0 1px 4px rgba(0,0,0,0.08); }
  .status-seg.active[data-status="Issue"] { background: var(--error-dim); color: var(--error); }
  .status-seg.active[data-status="Pending"] { background: var(--warning-bg); color: var(--warning); }
  .status-seg.active[data-status="Received"] { background: var(--success-dim); color: var(--success); }
  .status-seg.active[data-status="Closed"] { background: var(--card); color: var(--text-2); }
  .detail-close { background: none; border: none; cursor: pointer; color: var(--text-4); padding: var(--sp-1.5); border-radius: var(--radius-md); transition: all var(--transition); }
  .detail-close:hover { color: var(--text-1); background: var(--card-hover); }
  .detail-close svg { width: 18px; height: 18px; }

  /* ── Photos ── */
  .detail-photos { display: flex; gap: 10px; margin-bottom: var(--sp-5); overflow-x: auto; padding-bottom: var(--sp-1); }
  .detail-photos::-webkit-scrollbar { height: 4px; }
  .detail-photos::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }
  .photo-img { width: 140px; height: 105px; border-radius: 10px; object-fit: cover; flex-shrink: 0; background: var(--card-hover); }
  .photo-placeholder { width: 140px; height: 105px; border-radius: 10px; background: color-mix(in srgb, var(--surface) 70%, var(--card)); border: 1px dashed var(--border); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--sp-1.5); flex-shrink: 0; color: var(--text-4); }
  .photo-placeholder svg { width: 22px; height: 22px; opacity: 0.5; }
  .empty-photo { width: 100%; height: 90px; border-radius: 10px; }
  .empty-photo span { font-size: var(--text-sm); color: var(--text-4); }

  /* ── Actions ── */
  .actions-group { display: flex; flex-direction: column; gap: var(--sp-2); margin-bottom: var(--sp-7); }
  .actions-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-2); }
  .actions-row.secondary { grid-template-columns: repeat(2, 1fr); }
  .action-btn {
    display: flex; align-items: center; justify-content: center; gap: 5px;
    padding: 8px 14px; border-radius: var(--radius-md); height: 34px; width: 100%;
    background: var(--card); border: 1px solid var(--border);
    font-size: var(--text-sm); font-weight: 500; color: var(--text-3);
    cursor: pointer; font-family: var(--font);
    transition: all var(--transition);
  }
  .action-btn:hover { border-color: var(--text-4); color: var(--text-1); }
  .action-btn:active { transform: scale(0.97); }
  .action-btn.primary { background: var(--accent); border-color: var(--accent); color: white; }
  .action-btn.primary:hover { opacity: 0.9; border-color: var(--accent); color: white; }
  .action-btn.sm { padding: 6px 11px; font-size: var(--text-sm); height: 30px; }
  .action-btn.ghost { border-color: transparent; color: var(--text-4); background: none; }
  .action-btn.ghost:hover { color: var(--text-2); background: var(--card-hover); border-color: transparent; }
  .action-btn svg { width: 14px; height: 14px; }
  .action-btn.sm svg { width: 13px; height: 13px; }

  /* ── Section groups ── */
  .section-group { margin-bottom: var(--sp-7); }
  .section-label { font-size: var(--text-xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-2); margin-bottom: var(--sp-1.5); }

  /* ── Detail fields ── */
  .detail-fields { background: var(--card); border-radius: var(--radius); border: 1px solid var(--border); box-shadow: var(--shadow-sm); overflow: hidden; }
  .detail-row { display: flex; justify-content: space-between; align-items: center; padding: 14px 16px; }
  .detail-row + .detail-row { border-top: 1px solid var(--border); }
  .detail-row:nth-child(even) { background: color-mix(in srgb, var(--surface) 70%, var(--card)); }
  .field-label { font-size: var(--text-sm); color: var(--text-1); opacity: 0.65; letter-spacing: 0.01em; }
  .field-value { font-size: var(--text-base); font-weight: 400; color: var(--text-1); text-align: right; letter-spacing: -0.01em; }

  /* ── Inline editing ── */
  .detail-row.editable { cursor: pointer; }
  .detail-row.editable:hover { background: var(--card-hover); }
  .detail-title.editable { cursor: pointer; border-radius: var(--radius-sm); padding: 2px 4px; margin: -2px -4px; }
  .detail-title.editable:hover { background: var(--card-hover); }
  .edit-input {
    width: 100%; padding: 6px 10px; border-radius: var(--radius-sm);
    border: 1px solid var(--accent); background: var(--surface-secondary);
    color: var(--text-1); font-size: var(--text-base); font-family: var(--font);
    text-align: right; outline: none;
    box-shadow: 0 0 0 3px var(--accent-border);
  }
  .edit-input.mono { font-family: var(--mono); }
  .edit-input[type="number"] { font-family: var(--mono); }
  .detail-title-edit {
    font-size: var(--text-lg); font-weight: 600; text-align: left;
    flex: 1; min-width: 0;
  }
  .edit-textarea {
    text-align: left; resize: vertical; min-height: 60px;
    width: 100%; font-size: var(--text-sm); line-height: 1.5;
  }
  .detail-row.editing { background: var(--accent-dim); }
  .hidden-input { display: none; }
  .upload-menu {
    position: absolute; left: 0; right: 0; top: 100%; margin-top: var(--sp-1); z-index: 10;
    background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.12); overflow: hidden;
  }
  .upload-option {
    display: flex; align-items: center; gap: 10px; width: 100%;
    padding: 12px 16px; background: none; border: none; border-bottom: 1px solid var(--border);
    font-size: var(--text-base); font-weight: 500; color: var(--text-1); cursor: pointer;
    font-family: var(--font); transition: background var(--transition); text-align: left;
  }
  .upload-option:last-child { border-bottom: none; }
  .upload-option:hover { background: var(--card-hover); }
  .upload-option svg { width: 18px; height: 18px; color: var(--text-3); }
  .actions-row { position: relative; }
  .field-value.mono { font-family: var(--mono); }
  .field-value.strong { font-weight: 600; color: var(--text-1); }

  /* ── Mobile ── */
  @media (max-width: 768px) {
    .page-subtitle { font-size: var(--text-xl); }
    .detail-sheet { width: 100%; padding: var(--sp-5); }
    .detail-photos { gap: var(--sp-2); }
    .photo-img { width: 120px; height: 90px; }
    .photo-placeholder { width: 120px; height: 90px; }
    .detail-title { font-size: var(--text-lg); }
  }
</style>
