<template>
  <div class="p-6">
    <h1 v-if="view !== 'template-picker'" class="text-[1.75rem] font-bold font-[family-name:var(--font-heading)] tracking-tight text-text-primary mb-6">Invoices</h1>

    <!-- View tabs (hidden in template picker) -->
    <div v-if="view !== 'template-picker'" class="flex gap-6 mb-6 border-b border-border-subtle" role="tablist" aria-label="Invoice views" @keydown="onTabKeydown">
      <button
        id="tab-list"
        role="tab"
        :aria-selected="view === 'list'"
        aria-controls="tabpanel-list"
        :tabindex="view === 'list' ? 0 : -1"
        @click="view = 'list'"
        class="pb-2 text-[0.8125rem] transition-colors duration-150 -mb-px"
        :class="view === 'list'
          ? 'text-text-primary border-b-2 border-accent'
          : 'text-text-tertiary hover:text-text-secondary'"
      >
        List
      </button>
      <button
        id="tab-create"
        data-tour-id="new-invoice"
        role="tab"
        :aria-selected="view === 'create'"
        aria-controls="tabpanel-create"
        :tabindex="view === 'create' ? 0 : -1"
        @click="view = 'create'"
        class="pb-2 text-[0.8125rem] transition-colors duration-150 -mb-px"
        :class="view === 'create'
          ? 'text-text-primary border-b-2 border-accent'
          : 'text-text-tertiary hover:text-text-secondary'"
      >
        Create
      </button>
      <button
        id="tab-recurring"
        role="tab"
        :aria-selected="view === 'recurring'"
        aria-controls="tabpanel-recurring"
        :tabindex="view === 'recurring' ? 0 : -1"
        @click="view = 'recurring'; loadRecurringInvoices()"
        class="pb-2 text-[0.8125rem] transition-colors duration-150 -mb-px"
        :class="view === 'recurring'
          ? 'text-text-primary border-b-2 border-accent'
          : 'text-text-tertiary hover:text-text-secondary'"
      >
        Recurring
      </button>
      <button
        id="tab-pipeline"
        role="tab"
        :aria-selected="view === 'pipeline'"
        aria-controls="tabpanel-pipeline"
        :tabindex="view === 'pipeline' ? 0 : -1"
        @click="view = 'pipeline'"
        class="pb-2 text-[0.8125rem] transition-colors duration-150 -mb-px"
        :class="view === 'pipeline'
          ? 'text-text-primary border-b-2 border-accent'
          : 'text-text-tertiary hover:text-text-secondary'"
      >
        Pipeline
      </button>
    </div>

    <!-- Recurring View -->
    <div v-if="view === 'recurring'" id="tabpanel-recurring" role="tabpanel" aria-labelledby="tab-recurring">
      <div class="flex items-center justify-between mb-4">
        <p class="text-[0.75rem] text-text-secondary">Automatically create draft invoices on a schedule.</p>
        <button
          @click="openRecurringDialog(null)"
          class="px-3 py-1.5 bg-accent text-bg-base text-xs font-medium rounded-lg hover:bg-accent-hover transition-colors duration-150"
        >
          + Add
        </button>
      </div>

      <div v-if="recurringInvoices.length > 0" class="overflow-x-auto">
        <table class="w-full">
          <thead>
            <tr class="border-b border-border-subtle bg-bg-surface">
              <th class="px-4 py-3 text-left text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium">Client</th>
              <th class="px-4 py-3 text-left text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium">Frequency</th>
              <th class="px-4 py-3 text-left text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium">Next Due</th>
              <th class="px-4 py-3 text-center text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium">Status</th>
              <th class="px-4 py-3 w-20"><span class="sr-only">Actions</span></th>
            </tr>
          </thead>
          <tbody>
            <tr
              v-for="ri in recurringInvoices"
              :key="ri.id"
              class="border-b border-border-subtle last:border-0"
            >
              <td class="px-4 py-3 text-[0.75rem] text-text-primary">{{ getClientName(ri.client_id) }}</td>
              <td class="px-4 py-3 text-[0.75rem] text-text-secondary capitalize">{{ ri.recurrence_rule }}</td>
              <td class="px-4 py-3 text-[0.75rem] text-text-secondary">{{ formatDate(ri.next_due_date) }}</td>
              <td class="px-4 py-3 text-center">
                <span
                  class="inline-block px-2 py-0.5 text-[0.6875rem] font-medium rounded-full"
                  :class="ri.enabled ? 'bg-green-500/10 text-green-400' : 'bg-bg-elevated text-text-tertiary'"
                >
                  {{ ri.enabled ? 'Active' : 'Paused' }}
                </span>
              </td>
              <td class="px-4 py-3">
                <div class="flex items-center justify-end gap-1">
                  <button
                    @click="openRecurringDialog(ri)"
                    class="p-1.5 text-text-tertiary hover:text-text-secondary transition-colors"
                    aria-label="Edit recurring invoice"
                    v-tooltip="'Edit'"
                  >
                    <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-hidden="true">
                      <path stroke-linecap="round" stroke-linejoin="round" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
                    </svg>
                  </button>
                  <button
                    @click="deleteRecurring(ri.id)"
                    class="p-1.5 text-text-tertiary hover:text-status-error transition-colors"
                    aria-label="Delete recurring invoice"
                    v-tooltip="'Delete'"
                  >
                    <X class="w-3.5 h-3.5" :stroke-width="1.5" aria-hidden="true" />
                  </button>
                </div>
              </td>
            </tr>
          </tbody>
        </table>
      </div>

      <div v-else class="flex flex-col items-center justify-center py-16">
        <FileText class="w-12 h-12 text-text-tertiary" :stroke-width="1.5" aria-hidden="true" />
        <p class="text-sm text-text-secondary mt-4">No recurring invoices</p>
        <p class="text-xs text-text-tertiary mt-2 max-w-xs text-center">Set up automatic invoice creation for clients on a regular schedule.</p>
      </div>
    </div>

    <!-- Pipeline View -->
    <div v-if="view === 'pipeline'" id="tabpanel-pipeline" role="tabpanel" aria-labelledby="tab-pipeline">
      <InvoicePipelineView @open="openInvoiceFromPipeline" />
    </div>

    <!-- List View -->
    <div v-if="view === 'list'" id="tabpanel-list" role="tabpanel" aria-labelledby="tab-list">
      <!-- Status filter -->
      <div v-if="invoicesStore.invoices.length > 0" class="flex flex-wrap gap-2 mb-4" role="group" aria-label="Filter by status">
        <button
          v-for="opt in statusOptions"
          :key="opt.value"
          @click="statusFilter = opt.value"
          :aria-pressed="statusFilter === opt.value"
          class="px-3 py-1 text-[0.6875rem] font-medium rounded-full border transition-colors duration-150 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent"
          :class="statusFilter === opt.value
            ? 'bg-accent text-bg-base border-accent'
            : 'bg-bg-surface text-text-secondary border-border-subtle hover:border-border-visible'"
        >
          {{ opt.label }} ({{ getStatusCount(opt.value) }})
        </button>
      </div>

      <div v-if="filteredInvoices.length > 0" class="overflow-x-auto">
        <table class="w-full">
          <thead>
            <tr class="border-b border-border-subtle bg-bg-surface">
              <th class="px-4 py-3 text-left text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium">Invoice #</th>
              <th class="px-4 py-3 text-left text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium">Client</th>
              <th class="px-4 py-3 text-left text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium">Date</th>
              <th class="px-4 py-3 text-right text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium">Amount</th>
              <th class="px-4 py-3 text-center text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium">Status</th>
              <th class="px-4 py-3 w-32"><span class="sr-only">Actions</span></th>
            </tr>
          </thead>
          <tbody>
            <tr
              v-for="invoice in filteredInvoices"
              :key="invoice.id"
              class="group border-b border-border-subtle hover:bg-bg-elevated transition-colors duration-150"
            >
              <td class="px-4 py-3 text-[0.75rem] font-medium text-text-primary">
                {{ invoice.invoice_number }}
              </td>
              <td class="px-4 py-3 text-[0.75rem] text-text-primary">
                {{ getClientName(invoice.client_id) }}
              </td>
              <td class="px-4 py-3 text-[0.75rem] text-text-secondary">
                {{ formatDate(invoice.date) }}
              </td>
              <td class="px-4 py-3 text-right text-[0.75rem] font-mono text-accent-text">
                {{ formatCurrency(invoice.total) }}
              </td>
              <td class="px-4 py-3 text-center">
                <span
                  class="inline-block px-2 py-0.5 text-[0.6875rem] font-medium rounded-full capitalize"
                  :class="getStatusClass(invoice.status)"
                >
                  {{ invoice.status }}
                </span>
              </td>
              <td class="px-4 py-3">
                <div class="flex items-center justify-end gap-1">
                  <button
                    v-if="invoice.status === 'draft'"
                    @click="markInvoiceSent(invoice.id!)"
                    class="px-2 py-1 text-[0.625rem] font-medium text-blue-400 border border-blue-400/30 rounded hover:bg-blue-400/10 transition-colors duration-150 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent"
                    :aria-label="'Mark invoice ' + invoice.invoice_number + ' as sent'"
                  >
                    Mark Sent
                  </button>
                  <button
                    v-if="invoice.status === 'sent' || invoice.status === 'overdue' || invoice.status === 'partial'"
                    @click="openPaymentDialog(invoice)"
                    class="px-2 py-1 text-[0.625rem] font-medium text-green-400 border border-green-400/30 rounded hover:bg-green-400/10 transition-colors duration-150 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent"
                    :aria-label="'Record payment for invoice ' + invoice.invoice_number"
                  >
                    Record Payment
                  </button>
                  <div class="flex items-center gap-1">
                    <button
                      v-if="invoice.status !== 'draft'"
                      @click="emailInvoice(invoice)"
                      class="p-1.5 text-text-tertiary hover:text-text-secondary transition-colors duration-150"
                      :aria-label="'Email invoice ' + invoice.invoice_number"
                      v-tooltip="'Email'"
                    >
                      <Mail class="h-3.5 w-3.5" :stroke-width="1.5" aria-hidden="true" />
                    </button>
                    <button
                      @click="viewInvoice(invoice)"
                      class="p-1.5 text-text-tertiary hover:text-text-secondary transition-colors duration-150"
                      aria-label="View invoice"
                      v-tooltip="'View'"
                    >
                      <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-hidden="true">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
                        <path stroke-linecap="round" stroke-linejoin="round" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
                      </svg>
                    </button>
                    <button
                      @click="exportPDF(invoice)"
                      class="p-1.5 text-text-tertiary hover:text-text-secondary transition-colors duration-150"
                      aria-label="Export PDF"
                      v-tooltip="'Export PDF'"
                    >
                      <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-hidden="true">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
                      </svg>
                    </button>
                    <button
                      @click="confirmDelete(invoice)"
                      class="p-1.5 text-text-tertiary hover:text-status-error transition-colors duration-150"
                      aria-label="Delete invoice"
                      v-tooltip="'Delete'"
                    >
                      <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-hidden="true">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
                      </svg>
                    </button>
                  </div>
                </div>
              </td>
            </tr>
          </tbody>
        </table>
      </div>

      <div v-else-if="invoicesStore.invoices.length > 0 && filteredInvoices.length === 0" class="flex flex-col items-center justify-center py-16">
        <FileText class="w-12 h-12 text-text-tertiary" :stroke-width="1.5" aria-hidden="true" />
        <p class="text-sm text-text-secondary mt-4">No {{ statusFilter }} invoices</p>
        <button
          @click="statusFilter = 'all'"
          class="mt-4 px-4 py-2 border border-border-subtle text-text-secondary text-xs font-medium rounded-lg hover:bg-bg-elevated transition-colors"
        >
          Show All
        </button>
      </div>

      <div v-else class="flex flex-col items-center justify-center py-16">
        <FileText class="w-12 h-12 text-text-tertiary" :stroke-width="1.5" aria-hidden="true" />
        <p class="text-sm text-text-secondary mt-4">No invoices yet</p>
        <p class="text-xs text-text-tertiary mt-2 max-w-xs text-center">Create invoices from your tracked time to bill clients.</p>
        <button
          @click="view = 'create'"
          class="mt-4 px-4 py-2 bg-accent text-bg-base text-xs font-medium rounded-lg hover:bg-accent-hover transition-colors"
        >
          Create Invoice
        </button>
      </div>
    </div>

    <!-- Create View -->
    <div v-else-if="view === 'create'" id="tabpanel-create" role="tabpanel" aria-labelledby="tab-create" class="max-w-4xl mx-auto">
      <form @submit.prevent="handleCreate" class="space-y-5">
        <!-- Top: Invoice settings + Client info -->
        <div class="grid grid-cols-2 gap-6">
          <!-- Left: Invoice settings -->
          <div class="space-y-4">
            <div>
              <label for="invoice-number" class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Invoice Number</label>
              <div class="flex gap-2">
                <input
                  id="invoice-number"
                  v-model="createForm.invoice_number"
                  type="text"
                  class="flex-1 px-3 py-2 bg-bg-inset border border-border-subtle rounded-lg text-[0.8125rem] text-text-primary font-mono focus:outline-none focus:border-border-visible"
                  placeholder="INV-001"
                />
                <div class="relative group">
                  <button
                    type="button"
                    @click="showTokenHelp = !showTokenHelp"
                    class="px-2.5 py-2 border border-border-subtle text-text-tertiary rounded-lg hover:bg-bg-elevated hover:text-text-secondary transition-colors text-[0.75rem]"
                    aria-label="Token help"
                    :aria-expanded="showTokenHelp"
                    :aria-describedby="showTokenHelp ? 'token-help-popover' : undefined"
                  >
                    { }
                  </button>
                  <div
                    v-if="showTokenHelp"
                    id="token-help-popover"
                    role="tooltip"
                    class="absolute right-0 top-full mt-1 w-56 bg-bg-elevated border border-border-subtle rounded-lg shadow-lg p-3 z-20 text-[0.6875rem]"
                    @keydown.escape="showTokenHelp = false"
                  >
                    <p class="text-text-secondary mb-2">Available tokens:</p>
                    <div class="space-y-1 font-mono text-text-tertiary">
                      <p><span class="text-accent-text">{YYYY}</span> - {{ new Date().getFullYear() }}</p>
                      <p><span class="text-accent-text">{YY}</span> - {{ String(new Date().getFullYear()).slice(-2) }}</p>
                      <p><span class="text-accent-text">{MM}</span> - {{ String(new Date().getMonth() + 1).padStart(2, '0') }}</p>
                      <p><span class="text-accent-text">{DD}</span> - {{ String(new Date().getDate()).padStart(2, '0') }}</p>
                      <p><span class="text-accent-text">{###}</span> - next number ({{ String(invoicesStore.invoices.length + 1).padStart(3, '0') }})</p>
                    </div>
                    <p class="text-text-tertiary mt-2">e.g. INV-{YYYY}-{###}</p>
                  </div>
                </div>
              </div>
              <p v-if="resolvedInvoiceNumber !== createForm.invoice_number" class="text-[0.625rem] text-text-tertiary mt-1 font-mono">
                Preview: {{ resolvedInvoiceNumber }}
              </p>
            </div>

            <div>
              <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Client *</label>
              <AppSelect
                v-model="createForm.client_id"
                :options="clientsStore.clients"
                label-key="name"
                value-key="id"
                placeholder="Select a client"
                :placeholder-value="0"
              />
            </div>

            <div class="grid grid-cols-2 gap-4">
              <div>
                <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Invoice Date *</label>
                <AppDatePicker
                  v-model="createForm.date"
                  placeholder="Invoice date"
                />
              </div>
              <div>
                <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Due Date</label>
                <AppDatePicker
                  v-model="createForm.due_date"
                  placeholder="Due date"
                />
              </div>
            </div>
          </div>

          <!-- Right: Client info card -->
          <div>
            <div v-if="selectedClient" class="bg-bg-inset border border-border-subtle rounded-lg p-4 space-y-3">
              <div class="flex items-center justify-between">
                <h3 class="text-[0.8125rem] font-semibold text-text-primary">{{ selectedClient.name }}</h3>
                <span class="text-[0.625rem] text-text-tertiary uppercase tracking-wider">Bill To</span>
              </div>
              <div class="space-y-1.5 text-[0.75rem] text-text-secondary">
                <p v-if="selectedClient.company">{{ selectedClient.company }}</p>
                <p v-if="selectedClient.email">{{ selectedClient.email }}</p>
                <p v-if="selectedClient.phone">{{ selectedClient.phone }}</p>
                <p v-if="selectedClient.address" class="whitespace-pre-line">{{ selectedClient.address }}</p>
                <p v-if="selectedClient.tax_id" class="text-text-tertiary">Tax ID: {{ selectedClient.tax_id }}</p>
              </div>
              <p v-if="selectedClient.payment_terms" class="text-[0.6875rem] text-text-tertiary pt-2 border-t border-border-subtle">
                Terms: {{ selectedClient.payment_terms }}
              </p>
            </div>
            <div v-else class="bg-bg-inset border border-border-subtle rounded-lg p-4 flex items-center justify-center h-full min-h-[8rem]">
              <p class="text-[0.75rem] text-text-tertiary">Select a client to see their billing info</p>
            </div>
          </div>
        </div>

        <!-- Line Items -->
        <div class="bg-bg-surface border border-border-subtle rounded-lg overflow-hidden">
          <div class="flex items-center justify-between px-4 py-3 border-b border-border-subtle">
            <h3 class="text-[0.8125rem] font-medium text-text-primary">Line Items</h3>
            <div class="flex items-center gap-2">
              <AppSelect
                v-model="importProjectId"
                :options="projectsStore.projects"
                label-key="name"
                value-key="id"
                placeholder="Import from project..."
                :placeholder-value="0"
                class="w-48"
                @update:model-value="(v: number) => { if (v) previewImport(v) }"
              />
              <button
                type="button"
                @click="importFromProject"
                :disabled="!importProjectId"
                class="px-2.5 py-1.5 text-[0.75rem] font-medium bg-accent text-bg-base rounded-lg hover:bg-accent-hover transition-colors disabled:opacity-40 disabled:cursor-not-allowed"
              >
                Import
              </button>
              <button
                type="button"
                @click="importExpenses"
                :disabled="!createForm.client_id"
                class="flex items-center gap-1 px-2.5 py-1.5 text-[0.75rem] font-medium border border-border-subtle text-text-secondary rounded-lg hover:bg-bg-elevated transition-colors disabled:opacity-40 disabled:cursor-not-allowed"
              >
                <Receipt class="w-3 h-3" :stroke-width="2" aria-hidden="true" />
                Import Expenses
              </button>
              <button
                type="button"
                @click="addLineItem"
                class="px-2.5 py-1.5 text-[0.75rem] font-medium border border-border-subtle text-text-secondary rounded-lg hover:bg-bg-elevated transition-colors"
              >
                + Add Row
              </button>
            </div>
          </div>

          <!-- Import date range filter -->
          <div v-if="importProjectId" class="px-4 py-3 border-b border-border-subtle bg-bg-inset">
            <div class="flex items-center gap-3 flex-wrap">
              <div class="flex items-center gap-2">
                <label class="text-[0.6875rem] text-text-tertiary whitespace-nowrap">From</label>
                <AppDatePicker
                  :model-value="importStartDate"
                  @update:model-value="(v: string) => { importStartDate = v; previewImport(importProjectId) }"
                  placeholder="Start date"
                />
              </div>
              <div class="flex items-center gap-2">
                <label class="text-[0.6875rem] text-text-tertiary whitespace-nowrap">To</label>
                <AppDatePicker
                  :model-value="importEndDate"
                  @update:model-value="(v: string) => { importEndDate = v; previewImport(importProjectId) }"
                  placeholder="End date"
                />
              </div>
              <div v-if="importPreview" aria-live="polite" class="text-[0.6875rem] text-text-secondary ml-auto">
                {{ importPreview.count }} entries, {{ formatNumber(importPreview.hours, 1) }} hours, {{ formatCurrency(importPreview.amount) }}
              </div>
            </div>
          </div>

          <table v-if="lineItems.length > 0" class="w-full">
            <thead>
              <tr class="border-b border-border-subtle bg-bg-inset">
                <th class="px-4 py-2 text-left text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium">Description</th>
                <th class="px-4 py-2 text-center text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium w-36">Qty</th>
                <th class="px-4 py-2 text-center text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium w-40">Rate</th>
                <th class="px-4 py-2 text-right text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium w-28">Amount</th>
                <th class="px-4 py-2 w-10"></th>
              </tr>
            </thead>
            <tbody>
              <tr
                v-for="(item, i) in lineItems"
                :key="i"
                class="border-b border-border-subtle last:border-b-0"
              >
                <td class="px-4 py-1.5">
                  <input
                    v-model="item.description"
                    type="text"
                    class="w-full px-2 py-1 bg-transparent border-0 text-[0.75rem] text-text-primary focus:outline-none focus:bg-bg-inset rounded"
                    placeholder="Item description"
                    aria-label="Item description"
                  />
                </td>
                <td class="px-4 py-1.5">
                  <AppNumberInput
                    v-model="item.quantity"
                    :min="0"
                    :step="0.25"
                    :precision="2"
                    label="Quantity"
                    compact
                  />
                </td>
                <td class="px-4 py-1.5">
                  <AppNumberInput
                    v-model="item.unit_price"
                    :min="0"
                    :step="1"
                    :precision="2"
                    :prefix="getCurrencySymbol()"
                    label="Unit price"
                    compact
                  />
                </td>
                <td class="px-4 py-1.5 text-right text-[0.75rem] font-mono text-text-primary">
                  {{ formatCurrency(item.quantity * item.unit_price) }}
                </td>
                <td class="px-4 py-1.5">
                  <button
                    type="button"
                    @click="lineItems.splice(i, 1)"
                    class="p-1 text-text-tertiary hover:text-status-error transition-colors"
                    :aria-label="'Remove line item ' + (i + 1)"
                    v-tooltip="'Remove'"
                  >
                    <X class="w-3.5 h-3.5" :stroke-width="1.5" aria-hidden="true" />
                  </button>
                </td>
              </tr>
            </tbody>
          </table>
          <div v-else class="px-4 py-8 text-center text-[0.75rem] text-text-tertiary">
            No line items. Import from a project or add rows manually.
          </div>
        </div>

        <!-- Bottom: Totals + Notes side by side -->
        <div class="grid grid-cols-2 gap-6">
          <!-- Left: Notes -->
          <div>
            <label for="invoice-notes" class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Notes</label>
            <textarea
              id="invoice-notes"
              v-model="createForm.notes"
              rows="4"
              class="w-full px-3 py-2 bg-bg-inset border border-border-subtle rounded-lg text-[0.8125rem] text-text-primary focus:outline-none focus:border-border-visible resize-none"
              placeholder="Payment instructions, thank you message, etc."
            ></textarea>
          </div>

          <!-- Right: Totals -->
          <div>
            <div class="grid grid-cols-2 gap-4 mb-3">
              <div>
                <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Tax Rate (%)</label>
                <AppNumberInput
                  v-model="createForm.tax_rate"
                  :min="0"
                  :max="100"
                  :step="0.5"
                  :precision="2"
                  suffix="%"
                />
              </div>
              <div>
                <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Discount ({{ getCurrencySymbol() }})</label>
                <AppNumberInput
                  v-model="createForm.discount"
                  :min="0"
                  :step="1"
                  :precision="2"
                  :prefix="getCurrencySymbol()"
                />
              </div>
            </div>
            <div class="bg-bg-inset rounded-lg p-4">
              <div class="flex justify-between text-[0.75rem] text-text-secondary mb-2">
                <span>Subtotal:</span>
                <span class="font-mono">{{ formatCurrency(calculateSubtotal()) }}</span>
              </div>
              <div class="flex justify-between text-[0.75rem] text-text-secondary mb-2">
                <span>Tax ({{ createForm.tax_rate }}%):</span>
                <span class="font-mono">{{ formatCurrency(calculateTax()) }}</span>
              </div>
              <div v-if="createForm.discount > 0" class="flex justify-between text-[0.75rem] text-text-secondary mb-2">
                <span>Discount:</span>
                <span class="font-mono">-{{ formatCurrency(createForm.discount) }}</span>
              </div>
              <div class="flex justify-between text-text-primary font-medium text-[0.8125rem] pt-2 border-t border-border-subtle">
                <span>Total:</span>
                <span class="font-mono text-accent-text">{{ formatCurrency(calculateTotal()) }}</span>
              </div>
            </div>
          </div>
        </div>

        <!-- Rounding note -->
        <div v-if="isRoundingEnabled" class="text-[0.625rem] text-text-tertiary flex items-center gap-1">
          <Clock class="w-3 h-3 shrink-0" aria-hidden="true" :stroke-width="1.5" />
          Durations may include rounding adjustments
        </div>

        <!-- Buttons -->
        <div class="flex justify-end gap-3 pt-2">
          <button
            type="button"
            @click="view = 'list'"
            class="px-4 py-2 border border-border-subtle text-text-secondary rounded-lg hover:bg-bg-elevated transition-colors duration-150"
          >
            Cancel
          </button>
          <button
            type="submit"
            class="px-4 py-2 bg-accent text-bg-base font-medium rounded-lg hover:bg-accent-hover transition-colors duration-150"
          >
            Create Invoice
          </button>
        </div>
      </form>
    </div>

    <!-- Template Picker View -->
    <div v-else-if="view === 'template-picker'" class="fixed inset-0 z-40 bg-bg-base flex flex-col" role="dialog" aria-modal="true" aria-label="Template picker">
      <!-- Top bar -->
      <div class="flex items-center justify-between px-6 py-3 border-b border-border-subtle bg-bg-surface shrink-0">
        <div class="flex items-center gap-3">
          <button
            @click="handlePickerBack"
            class="p-1.5 text-text-tertiary hover:text-text-secondary transition-colors"
            aria-label="Back to invoice list"
            v-tooltip="'Back'"
          >
            <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-hidden="true">
              <path stroke-linecap="round" stroke-linejoin="round" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
            </svg>
          </button>
          <span class="text-[0.8125rem] font-medium text-text-primary">
            {{ selectedInvoice?.invoice_number }}
          </span>
          <span class="text-[0.75rem] text-text-tertiary">
            {{ selectedInvoice ? getClientName(selectedInvoice.client_id) : '' }}
          </span>
        </div>
        <div class="flex items-center gap-3">
          <button
            @click="handlePickerExport"
            class="px-4 py-2 bg-accent text-bg-base text-[0.75rem] font-medium rounded-lg hover:bg-accent-hover transition-colors"
          >
            Export PDF
          </button>
          <button
            @click="handlePickerSave"
            class="px-4 py-2 border border-border-subtle text-text-secondary text-[0.75rem] rounded-lg hover:bg-bg-elevated transition-colors"
          >
            Save &amp; Close
          </button>
        </div>
      </div>

      <!-- Split pane -->
      <div class="flex-1 flex overflow-hidden">
        <!-- Left: Template list -->
        <div class="w-56 border-r border-border-subtle overflow-y-auto bg-bg-surface shrink-0">
          <div v-for="cat in TEMPLATE_CATEGORIES" :key="cat.id">
            <div class="text-[0.5625rem] text-text-tertiary uppercase tracking-[0.08em] font-medium px-3 pt-3 pb-1">
              {{ cat.label }}
            </div>
            <button
              v-for="tmpl in getTemplatesByCategory(cat.id)"
              :key="tmpl.id"
              class="w-full flex items-center gap-2 px-3 py-1.5 text-[0.75rem] transition-colors"
              :class="tmpl.id === selectedTemplateId
                ? 'bg-accent/10 text-accent-text'
                : 'text-text-secondary hover:bg-bg-elevated hover:text-text-primary'"
              @click="selectedTemplateId = tmpl.id"
            >
              <span class="w-2.5 h-2.5 rounded-full shrink-0 border border-black/10" :style="{ backgroundColor: tmpl.colors.primary }" aria-hidden="true" />
              <span class="truncate">{{ tmpl.name }}</span>
            </button>
          </div>
        </div>

        <!-- Right: Preview -->
        <div class="flex-1 bg-bg-inset p-8 overflow-y-auto flex justify-center">
          <div class="w-full max-w-lg">
            <InvoicePreview
              v-if="selectedInvoice"
              :template="getTemplateById(selectedTemplateId)"
              :invoice="selectedInvoice"
              :client="pickerClient"
              :items="previewItems"
              :business-info="businessInfo"
            />
          </div>
        </div>
      </div>
    </div>

    <!-- Delete Confirmation Dialog -->
    <Transition name="modal">
    <div
      v-if="showDeleteDialog"
      class="fixed inset-0 bg-black/70 backdrop-blur-[4px] flex items-center justify-center p-4 z-50"
      @click.self="showDeleteDialog = false"
    >
      <div ref="deleteDialogRef" class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-sm p-6" role="alertdialog" aria-modal="true" aria-labelledby="delete-invoice-title" aria-describedby="delete-invoice-desc">
        <h2 id="delete-invoice-title" class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-2">Delete Invoice</h2>
        <p id="delete-invoice-desc" class="text-[0.75rem] text-text-secondary mb-6">
          Are you sure you want to delete invoice "{{ invoiceToDelete?.invoice_number }}"? This action cannot be undone.
        </p>
        <div class="flex justify-end gap-3">
          <button
            @click="showDeleteDialog = false"
            class="px-4 py-2 border border-border-subtle text-text-secondary rounded-lg hover:bg-bg-elevated transition-colors duration-150"
          >
            Cancel
          </button>
          <button
            @click="handleDelete"
            class="px-4 py-2 border border-status-error text-status-error-text font-medium rounded-lg hover:bg-status-error/10 transition-colors duration-150"
          >
            Delete
          </button>
        </div>
      </div>
    </div>
    </Transition>

    <!-- Payment Dialog -->
    <Transition name="modal">
    <div
      v-if="showPaymentDialog"
      class="fixed inset-0 bg-black/70 backdrop-blur-[4px] flex items-center justify-center p-4 z-50"
      @click.self="showPaymentDialog = false"
    >
      <div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-md p-6" role="dialog" aria-modal="true" aria-labelledby="payment-dialog-title">
        <h2 id="payment-dialog-title" class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-1">Record Payment</h2>
        <p class="text-[0.75rem] text-text-secondary mb-4">
          {{ paymentInvoice?.invoice_number }} - {{ formatCurrency(paymentInvoice?.total || 0) }} total, {{ formatCurrency(paymentRemaining) }} remaining
        </p>

        <!-- Existing payments -->
        <div v-if="invoicePayments.length > 0" class="mb-4 space-y-1.5">
          <p class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em]">Previous payments</p>
          <div
            v-for="pmt in invoicePayments"
            :key="pmt.id"
            class="flex items-center justify-between px-3 py-1.5 bg-bg-inset rounded-lg"
          >
            <div class="flex items-center gap-2">
              <span class="text-[0.75rem] font-mono text-accent-text">{{ formatCurrency(pmt.amount) }}</span>
              <span class="text-[0.625rem] text-text-tertiary">{{ formatDate(pmt.date) }}</span>
              <span v-if="pmt.method" class="text-[0.625rem] text-text-tertiary capitalize">{{ pmt.method }}</span>
            </div>
            <button
              @click="deletePayment(pmt.id)"
              class="p-1 text-text-tertiary hover:text-status-error transition-colors"
              :aria-label="'Delete payment of ' + formatCurrency(pmt.amount)"
              v-tooltip="'Delete'"
            >
              <X class="w-3 h-3" :stroke-width="1.5" aria-hidden="true" />
            </button>
          </div>
        </div>

        <form @submit.prevent="submitPayment" class="space-y-3">
          <div>
            <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Amount *</label>
            <AppNumberInput
              v-model="paymentForm.amount"
              :min="0"
              :step="1"
              :precision="2"
              :prefix="getCurrencySymbol()"
            />
            <button
              v-if="paymentRemaining > 0"
              type="button"
              @click="paymentForm.amount = paymentRemaining"
              class="mt-1 text-[0.625rem] text-accent-text hover:underline"
            >
              Pay remaining {{ formatCurrency(paymentRemaining) }}
            </button>
          </div>
          <div>
            <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Date</label>
            <AppDatePicker v-model="paymentForm.date" placeholder="Payment date" />
          </div>
          <div>
            <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Method</label>
            <AppSelect
              v-model="paymentForm.method"
              :options="paymentMethods"
              label-key="label"
              value-key="value"
              placeholder="Select method"
              :placeholder-value="''"
            />
          </div>
          <div>
            <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Notes</label>
            <input
              v-model="paymentForm.notes"
              type="text"
              class="w-full px-3 py-2 bg-bg-inset border border-border-subtle rounded-lg text-[0.8125rem] text-text-primary focus:outline-none focus:border-border-visible"
              placeholder="Optional payment note"
            />
          </div>
          <div class="flex justify-end gap-3 pt-2">
            <button
              type="button"
              @click="showPaymentDialog = false"
              class="px-4 py-2 border border-border-subtle text-text-secondary rounded-lg hover:bg-bg-elevated transition-colors duration-150"
            >
              Close
            </button>
            <button
              type="submit"
              :disabled="!paymentForm.amount || paymentForm.amount <= 0"
              class="px-4 py-2 bg-accent text-bg-base font-medium rounded-lg hover:bg-accent-hover transition-colors duration-150 disabled:opacity-40 disabled:cursor-not-allowed"
            >
              Record Payment
            </button>
          </div>
        </form>
      </div>
    </div>
    </Transition>
    <!-- Recurring Invoice Dialog -->
    <Transition name="modal">
    <div
      v-if="showRecurringDialog"
      class="fixed inset-0 bg-black/70 backdrop-blur-[4px] flex items-center justify-center p-4 z-50"
      @click.self="showRecurringDialog = false"
    >
      <div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-md p-6" role="dialog" aria-modal="true" aria-labelledby="recurring-dialog-title">
        <h2 id="recurring-dialog-title" class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">
          {{ editingRecurring ? 'Edit Recurring Invoice' : 'New Recurring Invoice' }}
        </h2>

        <form @submit.prevent="submitRecurring" class="space-y-4">
          <div>
            <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Client *</label>
            <AppSelect
              v-model="recurringForm.client_id"
              :options="clientsStore.clients"
              label-key="name"
              value-key="id"
              placeholder="Select a client"
              :placeholder-value="0"
            />
          </div>
          <div>
            <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Frequency *</label>
            <AppSelect
              v-model="recurringForm.recurrence_rule"
              :options="recurrenceOptions"
              label-key="label"
              value-key="value"
              placeholder="Select frequency"
              :placeholder-value="''"
            />
          </div>
          <div>
            <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Next Due Date *</label>
            <AppDatePicker v-model="recurringForm.next_due_date" placeholder="Next due date" />
          </div>
          <div class="grid grid-cols-2 gap-4">
            <div>
              <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Tax Rate (%)</label>
              <AppNumberInput v-model="recurringForm.tax_rate" :min="0" :max="100" :step="0.5" :precision="2" suffix="%" />
            </div>
            <div>
              <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Discount</label>
              <AppNumberInput v-model="recurringForm.discount" :min="0" :step="1" :precision="2" :prefix="getCurrencySymbol()" />
            </div>
          </div>
          <div>
            <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Notes</label>
            <input
              v-model="recurringForm.notes"
              type="text"
              class="w-full px-3 py-2 bg-bg-inset border border-border-subtle rounded-lg text-[0.8125rem] text-text-primary focus:outline-none focus:border-border-visible"
              placeholder="Optional notes for generated invoices"
            />
          </div>
          <div class="flex items-center gap-2">
            <input
              id="recurring-enabled"
              v-model="recurringForm.enabled"
              type="checkbox"
              class="w-4 h-4 rounded border-border-subtle text-accent focus:ring-accent"
            />
            <label for="recurring-enabled" class="text-[0.8125rem] text-text-primary">Enabled</label>
          </div>
          <div class="flex justify-end gap-3 pt-2">
            <button
              type="button"
              @click="showRecurringDialog = false"
              class="px-4 py-2 border border-border-subtle text-text-secondary rounded-lg hover:bg-bg-elevated transition-colors duration-150"
            >
              Cancel
            </button>
            <button
              type="submit"
              :disabled="!recurringForm.client_id || !recurringForm.recurrence_rule || !recurringForm.next_due_date"
              class="px-4 py-2 bg-accent text-bg-base font-medium rounded-lg hover:bg-accent-hover transition-colors duration-150 disabled:opacity-40 disabled:cursor-not-allowed"
            >
              {{ editingRecurring ? 'Update' : 'Create' }}
            </button>
          </div>
        </form>
      </div>
    </div>
    </Transition>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, onMounted, watch } from 'vue'
import { FileText, X, Receipt, Clock, Mail } from 'lucide-vue-next'
import { invoke } from '@tauri-apps/api/core'
import { save } from '@tauri-apps/plugin-dialog'
import AppNumberInput from '../components/AppNumberInput.vue'
import AppSelect from '../components/AppSelect.vue'
import AppDatePicker from '../components/AppDatePicker.vue'
import InvoicePreview from '../components/InvoicePreview.vue'
import InvoicePipelineView from '../components/InvoicePipelineView.vue'
import { getTemplateById, getTemplatesByCategory, loadTemplates, TEMPLATE_CATEGORIES } from '../utils/invoiceTemplates'
import type { BusinessInfo } from '../utils/invoicePdfRenderer'
import { useInvoicesStore, type Invoice, type InvoiceItem } from '../stores/invoices'
import { useClientsStore, type Client } from '../stores/clients'
import { useProjectsStore } from '../stores/projects'
import { useSettingsStore } from '../stores/settings'
import { useToastStore } from '../stores/toast'
import { generateInvoicePdf } from '../utils/invoicePdf'
import { useExpensesStore } from '../stores/expenses'
import { formatDate, formatCurrency, formatNumber, getCurrencySymbol } from '../utils/locale'
import { useFocusTrap } from '../utils/focusTrap'

interface LineItem {
  description: string
  quantity: number
  unit_price: number
}

const invoicesStore = useInvoicesStore()
const clientsStore = useClientsStore()
const projectsStore = useProjectsStore()
const settingsStore = useSettingsStore()
const toastStore = useToastStore()
const expensesStore = useExpensesStore()

// Track imported expense IDs so we can mark them invoiced after save
const importedExpenseIds = ref<number[]>([])

// View state
const view = ref<'list' | 'create' | 'template-picker' | 'pipeline' | 'recurring'>('list')
const pickerInvoiceId = ref<number | null>(null)

// Dialog state
const showDeleteDialog = ref(false)
const selectedInvoice = ref<Invoice | null>(null)
const invoiceToDelete = ref<Invoice | null>(null)

// Status filter
const statusFilter = ref('all')
const statusOptions = [
  { label: 'All', value: 'all' },
  { label: 'Draft', value: 'draft' },
  { label: 'Sent', value: 'sent' },
  { label: 'Partial', value: 'partial' },
  { label: 'Paid', value: 'paid' },
  { label: 'Overdue', value: 'overdue' },
]

const filteredInvoices = computed(() => {
  if (statusFilter.value === 'all') return invoicesStore.invoices
  return invoicesStore.invoices.filter(i => i.status === statusFilter.value)
})

function getStatusClass(status: string): string {
  switch (status) {
    case 'draft': return 'bg-bg-elevated text-text-tertiary'
    case 'sent': return 'bg-blue-500/10 text-blue-400'
    case 'partial': return 'bg-amber-500/10 text-amber-400'
    case 'paid': return 'bg-green-500/10 text-green-400'
    case 'overdue': return 'bg-red-500/10 text-red-400'
    default: return 'bg-bg-elevated text-text-tertiary'
  }
}

function getStatusCount(status: string): number {
  if (status === 'all') return invoicesStore.invoices.length
  return invoicesStore.invoices.filter(i => i.status === status).length
}

// Create form
const createForm = reactive({
  client_id: 0,
  invoice_number: 'INV-{YYYY}-{###}',
  date: new Date().toISOString().split('T')[0],
  due_date: '',
  tax_rate: 0,
  discount: 0,
  notes: ''
})

// Line items
const lineItems = ref<LineItem[]>([])
const importProjectId = ref(0)
const showTokenHelp = ref(false)

// Import date filtering
const importStartDate = ref(new Date(new Date().getFullYear(), new Date().getMonth(), 1).toISOString().split('T')[0])
const importEndDate = ref(new Date().toISOString().split('T')[0])
const importPreview = ref<{ count: number; hours: number; amount: number } | null>(null)

async function previewImport(projectId: number) {
  try {
    const entries = await invoke<any[]>('get_time_entries', {
      startDate: importStartDate.value,
      endDate: importEndDate.value,
    })
    const filtered = entries.filter((e: any) => e.project_id === projectId)
    const totalSeconds = filtered.reduce((sum: number, e: any) => sum + e.duration, 0)
    const hours = totalSeconds / 3600
    const project = projectsStore.projects.find(p => p.id === projectId)
    const rate = project?.hourly_rate || 0
    importPreview.value = { count: filtered.length, hours, amount: hours * rate }
  } catch (e) {
    console.error('Failed to preview import:', e)
    importPreview.value = null
  }
}
const selectedTemplateId = ref('clean')

// Delete dialog focus trap
const deleteDialogRef = ref<HTMLElement | null>(null)
const { activate: activateDeleteTrap, deactivate: deactivateDeleteTrap } = useFocusTrap()

watch(showDeleteDialog, (val) => {
  if (val) {
    setTimeout(() => {
      if (deleteDialogRef.value) activateDeleteTrap(deleteDialogRef.value, { onDeactivate: () => { showDeleteDialog.value = false } })
    }, 50)
  } else {
    deactivateDeleteTrap()
  }
})

// Clear imported expense IDs when leaving create view
watch(view, (newView, oldView) => {
  if (oldView === 'create' && newView !== 'create') {
    importedExpenseIds.value = []
  }
})

// Arrow key navigation for tabs
function openInvoiceFromPipeline(_id: number) {
  view.value = 'list'
}

function onTabKeydown(e: KeyboardEvent) {
  const tabs: Array<'list' | 'create'> = ['list', 'create']
  const current = tabs.indexOf(view.value as 'list' | 'create')
  if (current === -1) return
  let next = current
  if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {
    e.preventDefault()
    next = (current + 1) % tabs.length
  } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {
    e.preventDefault()
    next = (current - 1 + tabs.length) % tabs.length
  } else if (e.key === 'Home') {
    e.preventDefault()
    next = 0
  } else if (e.key === 'End') {
    e.preventDefault()
    next = tabs.length - 1
  } else {
    return
  }
  view.value = tabs[next]
  document.getElementById(`tab-${tabs[next]}`)?.focus()
}

// Preview / picker state
const previewItems = ref<InvoiceItem[]>([])
const pickerClient = computed<Client | null>(() => {
  if (!selectedInvoice.value) return null
  return clientsStore.clients.find(c => c.id === selectedInvoice.value!.client_id) || null
})

// Selected client info
const selectedClient = computed<Client | null>(() => {
  if (!createForm.client_id) return null
  return clientsStore.clients.find(c => c.id === createForm.client_id) || null
})

const isRoundingEnabled = computed(() => settingsStore.settings.rounding_enabled === 'true')

const businessInfo = computed<BusinessInfo>(() => ({
  name: settingsStore.settings.business_name || '',
  address: settingsStore.settings.business_address || '',
  email: settingsStore.settings.business_email || '',
  phone: settingsStore.settings.business_phone || '',
  logo: settingsStore.settings.business_logo || '',
}))

// Resolve invoice number tokens
const resolvedInvoiceNumber = computed(() => {
  const now = new Date()
  const nextNum = invoicesStore.invoices.length + 1
  return createForm.invoice_number
    .replace(/\{YYYY\}/g, String(now.getFullYear()))
    .replace(/\{YY\}/g, String(now.getFullYear()).slice(-2))
    .replace(/\{MM\}/g, String(now.getMonth() + 1).padStart(2, '0'))
    .replace(/\{DD\}/g, String(now.getDate()).padStart(2, '0'))
    .replace(/\{###\}/g, String(nextNum).padStart(3, '0'))
    .replace(/\{##\}/g, String(nextNum).padStart(2, '0'))
})

// Get client name by ID
function getClientName(clientId: number): string {
  const client = clientsStore.clients.find(c => c.id === clientId)
  return client?.name || 'Unknown Client'
}

// Add empty line item
function addLineItem() {
  lineItems.value.push({ description: '', quantity: 1, unit_price: 0 })
}

// Import line items from a project's time entries
async function importFromProject() {
  if (!importProjectId.value) return
  const project = projectsStore.projects.find(p => p.id === importProjectId.value)
  if (!project) return

  try {
    const entries = await invoke<{ duration: number; description?: string }[]>('get_time_entries', {
      startDate: importStartDate.value,
      endDate: importEndDate.value,
    })
    const projectEntries = entries.filter((e: any) => e.project_id === importProjectId.value)
    const totalHours = projectEntries.reduce((sum, e) => sum + e.duration / 3600, 0)

    if (totalHours > 0) {
      lineItems.value.push({
        description: `${project.name} - ${formatNumber(totalHours, 1)}h tracked`,
        quantity: parseFloat(totalHours.toFixed(2)),
        unit_price: project.hourly_rate
      })
    } else {
      toastStore.info('No time entries found for this project in the selected date range')
    }
  } catch (e) {
    console.error('Failed to import entries:', e)
  }
  importProjectId.value = 0
  importPreview.value = null
}

// Import uninvoiced expenses for the selected client
async function importExpenses() {
  if (!createForm.client_id) return

  try {
    const expenses = await expensesStore.fetchUninvoiced(undefined, createForm.client_id)
    if (expenses.length === 0) {
      toastStore.info('No uninvoiced expenses found for this client')
      return
    }

    for (const exp of expenses) {
      if (exp.id && importedExpenseIds.value.includes(exp.id)) continue
      const desc = exp.description
        ? `[${exp.category}] ${exp.description}`
        : `[${exp.category}]`
      lineItems.value.push({
        description: desc,
        quantity: 1,
        unit_price: exp.amount
      })
      if (exp.id) {
        importedExpenseIds.value.push(exp.id)
      }
    }
    toastStore.success(`Imported ${expenses.length} expense(s)`)
  } catch (e) {
    console.error('Failed to import expenses:', e)
    toastStore.error('Failed to import expenses')
  }
}

// Calculate subtotal from line items
function calculateSubtotal(): number {
  return lineItems.value.reduce((sum, item) => sum + (item.quantity * item.unit_price), 0)
}

// Calculate tax
function calculateTax(): number {
  return calculateSubtotal() * (createForm.tax_rate / 100)
}

// Calculate total
function calculateTotal(): number {
  return calculateSubtotal() + calculateTax() - createForm.discount
}

async function markInvoiceSent(id: number) {
  try {
    await invoicesStore.updateStatus(id, 'sent')
  } catch (e) {
    console.error('Failed to mark invoice as sent:', e)
    toastStore.error('Failed to mark invoice as sent')
  }
}

// View invoice -> open template picker
async function viewInvoice(invoice: Invoice) {
  selectedInvoice.value = invoice
  pickerInvoiceId.value = invoice.id!
  selectedTemplateId.value = invoice.template_id || 'clean'
  try {
    previewItems.value = invoice.id ? await invoicesStore.getInvoiceItems(invoice.id) : []
  } catch (e) {
    console.error('Failed to load invoice items:', e)
    toastStore.error('Failed to load invoice items')
    previewItems.value = []
  }
  view.value = 'template-picker'
}

// Confirm delete
function confirmDelete(invoice: Invoice) {
  invoiceToDelete.value = invoice
  showDeleteDialog.value = true
}

// Handle delete
async function handleDelete() {
  if (invoiceToDelete.value?.id) {
    await invoicesStore.deleteInvoice(invoiceToDelete.value.id)
  }
  showDeleteDialog.value = false
  invoiceToDelete.value = null
}

// =============================================
// PAYMENTS
// =============================================

interface InvoicePayment {
  id: number
  invoice_id: number
  amount: number
  date: string
  method: string
  notes: string
}

const showPaymentDialog = ref(false)
const paymentInvoice = ref<Invoice | null>(null)
const invoicePayments = ref<InvoicePayment[]>([])

const paymentForm = reactive({
  amount: 0,
  date: new Date().toISOString().split('T')[0],
  method: '',
  notes: '',
})

const paymentMethods = [
  { label: 'Bank Transfer', value: 'bank_transfer' },
  { label: 'Credit Card', value: 'credit_card' },
  { label: 'PayPal', value: 'paypal' },
  { label: 'Check', value: 'check' },
  { label: 'Cash', value: 'cash' },
  { label: 'Other', value: 'other' },
]

const paymentRemaining = computed(() => {
  if (!paymentInvoice.value) return 0
  const paid = invoicePayments.value.reduce((sum, p) => sum + p.amount, 0)
  return Math.max(0, paymentInvoice.value.total - paid)
})

async function openPaymentDialog(invoice: Invoice) {
  paymentInvoice.value = invoice
  paymentForm.amount = 0
  paymentForm.date = new Date().toISOString().split('T')[0]
  paymentForm.method = ''
  paymentForm.notes = ''

  try {
    invoicePayments.value = await invoke<InvoicePayment[]>('get_invoice_payments', { invoiceId: invoice.id })
  } catch {
    invoicePayments.value = []
  }

  showPaymentDialog.value = true
}

async function submitPayment() {
  if (!paymentInvoice.value?.id || !paymentForm.amount || paymentForm.amount <= 0) return

  try {
    await invoke('add_invoice_payment', {
      payment: {
        id: 0,
        invoice_id: paymentInvoice.value.id,
        amount: paymentForm.amount,
        date: paymentForm.date,
        method: paymentForm.method,
        notes: paymentForm.notes,
      }
    })

    // Refresh payments and invoice list
    invoicePayments.value = await invoke<InvoicePayment[]>('get_invoice_payments', { invoiceId: paymentInvoice.value.id })
    await invoicesStore.fetchInvoices()

    // Update local reference
    const updated = invoicesStore.invoices.find(i => i.id === paymentInvoice.value?.id)
    if (updated) paymentInvoice.value = updated

    // Reset form for next payment
    paymentForm.amount = 0
    paymentForm.notes = ''

    toastStore.success('Payment recorded')
  } catch (e) {
    console.error('Failed to record payment:', e)
    toastStore.error('Failed to record payment')
  }
}

async function deletePayment(paymentId: number) {
  if (!paymentInvoice.value?.id) return

  try {
    await invoke('delete_invoice_payment', { id: paymentId, invoiceId: paymentInvoice.value.id })
    invoicePayments.value = await invoke<InvoicePayment[]>('get_invoice_payments', { invoiceId: paymentInvoice.value.id })
    await invoicesStore.fetchInvoices()

    const updated = invoicesStore.invoices.find(i => i.id === paymentInvoice.value?.id)
    if (updated) paymentInvoice.value = updated

    toastStore.success('Payment deleted')
  } catch (e) {
    console.error('Failed to delete payment:', e)
    toastStore.error('Failed to delete payment')
  }
}

// =============================================
// RECURRING INVOICES
// =============================================

interface RecurringInvoice {
  id: number
  client_id: number
  template_id: string
  line_items_json: string
  tax_rate: number
  discount: number
  notes: string
  recurrence_rule: string
  next_due_date: string
  enabled: boolean
}

const recurringInvoices = ref<RecurringInvoice[]>([])
const showRecurringDialog = ref(false)
const editingRecurring = ref<RecurringInvoice | null>(null)

const recurringForm = reactive({
  client_id: 0,
  recurrence_rule: '',
  next_due_date: '',
  tax_rate: 0,
  discount: 0,
  notes: '',
  enabled: true,
})

const recurrenceOptions = [
  { label: 'Weekly', value: 'weekly' },
  { label: 'Biweekly', value: 'biweekly' },
  { label: 'Monthly', value: 'monthly' },
  { label: 'Quarterly', value: 'quarterly' },
  { label: 'Yearly', value: 'yearly' },
]

async function loadRecurringInvoices() {
  try {
    recurringInvoices.value = await invoke<RecurringInvoice[]>('get_recurring_invoices')
  } catch {
    recurringInvoices.value = []
  }
}

function openRecurringDialog(ri: RecurringInvoice | null) {
  editingRecurring.value = ri
  if (ri) {
    recurringForm.client_id = ri.client_id
    recurringForm.recurrence_rule = ri.recurrence_rule
    recurringForm.next_due_date = ri.next_due_date
    recurringForm.tax_rate = ri.tax_rate
    recurringForm.discount = ri.discount
    recurringForm.notes = ri.notes
    recurringForm.enabled = ri.enabled
  } else {
    recurringForm.client_id = 0
    recurringForm.recurrence_rule = ''
    recurringForm.next_due_date = ''
    recurringForm.tax_rate = 0
    recurringForm.discount = 0
    recurringForm.notes = ''
    recurringForm.enabled = true
  }
  showRecurringDialog.value = true
}

async function submitRecurring() {
  if (!recurringForm.client_id || !recurringForm.recurrence_rule || !recurringForm.next_due_date) return

  const payload = {
    id: editingRecurring.value?.id || 0,
    client_id: recurringForm.client_id,
    template_id: editingRecurring.value?.template_id || 'clean',
    line_items_json: editingRecurring.value?.line_items_json || '[]',
    tax_rate: recurringForm.tax_rate,
    discount: recurringForm.discount,
    notes: recurringForm.notes,
    recurrence_rule: recurringForm.recurrence_rule,
    next_due_date: recurringForm.next_due_date,
    enabled: recurringForm.enabled,
  }

  try {
    if (editingRecurring.value) {
      await invoke('update_recurring_invoice', { invoice: payload })
    } else {
      await invoke('create_recurring_invoice', { invoice: payload })
    }
    await loadRecurringInvoices()
    showRecurringDialog.value = false
    toastStore.success(editingRecurring.value ? 'Recurring invoice updated' : 'Recurring invoice created')
  } catch (e) {
    console.error('Failed to save recurring invoice:', e)
    toastStore.error('Failed to save recurring invoice')
  }
}

async function deleteRecurring(id: number) {
  try {
    await invoke('delete_recurring_invoice', { id })
    await loadRecurringInvoices()
    toastStore.success('Recurring invoice deleted')
  } catch (e) {
    console.error('Failed to delete recurring invoice:', e)
    toastStore.error('Failed to delete recurring invoice')
  }
}

// Handle create
async function handleCreate() {
  if (!createForm.client_id) {
    toastStore.info('Please select a client')
    return
  }

  const subtotal = calculateSubtotal()
  const taxAmount = subtotal * (createForm.tax_rate / 100)
  const total = subtotal + taxAmount - createForm.discount

  const invoice: Invoice = {
    client_id: createForm.client_id,
    invoice_number: resolvedInvoiceNumber.value,
    date: createForm.date,
    due_date: createForm.due_date || undefined,
    subtotal,
    tax_rate: createForm.tax_rate,
    tax_amount: taxAmount,
    discount: createForm.discount,
    total,
    notes: createForm.notes || undefined,
    status: 'draft'
  }

  const invoiceId = await invoicesStore.createInvoice(invoice)
  if (!invoiceId) {
    toastStore.error('Failed to create invoice')
    return
  }

  // Save line items
  if (lineItems.value.length > 0) {
    try {
      await invoicesStore.saveInvoiceItems(invoiceId, lineItems.value)
    } catch (e) {
      console.error('Failed to save line items:', e)
      toastStore.error('Invoice created but line items failed to save')
    }
  }

  // Mark imported expenses as invoiced
  if (importedExpenseIds.value.length > 0) {
    try {
      await expensesStore.markInvoiced(importedExpenseIds.value)
    } catch (e) {
      console.error('Failed to mark expenses as invoiced:', e)
    }
  }

  // Navigate to template picker with the new invoice
  selectedInvoice.value = { ...invoice, id: invoiceId }
  pickerInvoiceId.value = invoiceId
  selectedTemplateId.value = 'clean'
  previewItems.value = lineItems.value.map(li => ({
    invoice_id: invoiceId,
    description: li.description,
    quantity: li.quantity,
    rate: li.unit_price,
    amount: li.quantity * li.unit_price,
  }))

  // Reset form for next use
  createForm.client_id = 0
  createForm.invoice_number = 'INV-{YYYY}-{###}'
  createForm.date = new Date().toISOString().split('T')[0]
  createForm.due_date = ''
  createForm.tax_rate = 0
  createForm.discount = 0
  createForm.notes = ''
  lineItems.value = []
  importedExpenseIds.value = []

  view.value = 'template-picker'
}

// Template picker actions
async function handlePickerSave() {
  try {
    if (pickerInvoiceId.value) {
      await invoicesStore.updateInvoiceTemplate(pickerInvoiceId.value, selectedTemplateId.value)
    }
    pickerInvoiceId.value = null
    selectedInvoice.value = null
    view.value = 'list'
  } catch (e) {
    console.error('Failed to save template:', e)
    toastStore.error('Failed to save invoice template')
  }
}

async function handlePickerExport() {
  if (selectedInvoice.value) {
    await exportPDF(selectedInvoice.value)
  }
}

function handlePickerBack() {
  pickerInvoiceId.value = null
  selectedInvoice.value = null
  view.value = 'list'
}

// Export PDF using Tauri file save dialog
async function exportPDF(invoice: Invoice) {
  const client = clientsStore.clients.find(c => c.id === invoice.client_id)
  if (!client) {
    toastStore.error('Client not found for invoice')
    return
  }

  try {
    const items = invoice.id ? await invoicesStore.getInvoiceItems(invoice.id) : []
    const doc = generateInvoicePdf(invoice, client, items, selectedTemplateId.value, businessInfo.value)

    // Use Tauri's save dialog instead of jsPDF's browser-based save
    const filePath = await save({
      defaultPath: `${invoice.invoice_number}.pdf`,
      filters: [{ name: 'PDF', extensions: ['pdf'] }]
    })
    if (!filePath) return // User cancelled

    const pdfBytes = doc.output('arraybuffer')
    await invoke('save_binary_file', { path: filePath, data: Array.from(new Uint8Array(pdfBytes)) })
    toastStore.success('PDF exported successfully')
  } catch (e) {
    console.error('Failed to export PDF:', e)
    toastStore.error('Failed to export PDF')
  }
}

// Email invoice via system mail client
function emailInvoice(invoice: Invoice) {
  const client = clientsStore.clients.find(c => c.id === invoice.client_id)
  if (!client) {
    toastStore.error('Client not found for invoice')
    return
  }

  if (!client.email) {
    toastStore.info('No email address set for this client - add one in the Clients page')
    return
  }

  const subject = encodeURIComponent(`Invoice ${invoice.invoice_number}`)
  const body = encodeURIComponent(
    `Hi ${client.name},\n\n` +
    `Please find attached invoice ${invoice.invoice_number} for ${formatCurrency(invoice.total)}.\n\n` +
    (invoice.due_date ? `Payment is due by ${invoice.due_date}.\n\n` : '') +
    `Thank you for your business.\n\n` +
    `${settingsStore.settings.business_name || ''}`
  )

  window.open(`mailto:${client.email}?subject=${subject}&body=${body}`)
  toastStore.info('Mail client opened - export the PDF and attach it to the email')
}

// Load data on mount
onMounted(async () => {
  await Promise.all([
    invoicesStore.fetchInvoices(),
    clientsStore.fetchClients(),
    projectsStore.fetchProjects(),
    settingsStore.fetchSettings(),
    loadTemplates(),
  ])

  // Auto-create any due recurring invoices
  try {
    const today = new Date().toISOString().split('T')[0]
    const created = await invoke<number>('check_recurring_invoices', { today })
    if (created > 0) {
      await invoicesStore.fetchInvoices()
      toastStore.info(`${created} recurring invoice(s) created`)
    }
  } catch {
    // Ignore - recurring check is best-effort
  }
})
</script>
