<template>
  <div class="p-6">
    <h1 class="text-[1.75rem] font-bold font-[family-name:var(--font-heading)] tracking-tight text-text-primary mb-6">Reports</h1>

    <!-- Date Range Selector -->
    <div data-tour-id="reports-daterange" class="bg-bg-surface rounded-lg p-4 mb-6 flex flex-wrap items-end gap-4">
      <AppDateRangePresets
        :start-date="startDate"
        :end-date="endDate"
        @select="({ start, end }) => { startDate = start; endDate = end; fetchReport() }"
        class="mb-3 w-full"
      />
      <div>
        <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Start Date</label>
        <AppDatePicker
          v-model="startDate"
          placeholder="Start date"
        />
      </div>
      <div>
        <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">End Date</label>
        <AppDatePicker
          v-model="endDate"
          placeholder="End date"
        />
      </div>
      <div>
        <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Billable</label>
        <AppSelect
          v-model="billableFilter"
          :options="billableFilterOptions"
          label-key="label"
          value-key="value"
        />
      </div>
      <button
        data-tour-id="reports-generate"
        @click="fetchReport"
        class="px-4 py-2 bg-accent text-bg-base text-xs font-medium rounded-lg hover:bg-accent-hover transition-colors duration-150"
      >
        Generate
      </button>
      <button
        @click="exportCSV"
        class="px-4 py-2 border border-border-visible text-text-primary text-xs rounded-lg hover:bg-bg-elevated transition-colors duration-150"
      >
        Export CSV
      </button>
      <button
        @click="exportPDF"
        class="px-4 py-2 border border-border-visible text-text-primary text-xs rounded-lg hover:bg-bg-elevated transition-colors duration-150"
      >
        Export PDF
      </button>
    </div>

    <!-- Tab Buttons -->
    <div data-tour-id="reports-tabs" class="flex items-center gap-2 mb-6" role="tablist" aria-label="Report type" @keydown="onTabKeydown">
      <button
        @click="activeTab = 'hours'"
        role="tab"
        :aria-selected="activeTab === 'hours'"
        aria-controls="tabpanel-hours"
        id="tab-hours"
        :tabindex="activeTab === 'hours' ? 0 : -1"
        class="px-4 py-2 text-[0.75rem] font-medium rounded-lg transition-colors"
        :class="activeTab === 'hours' ? 'bg-accent text-bg-base' : 'text-text-secondary hover:text-text-primary'"
      >
        <span class="flex items-center gap-1.5">
          <BarChart3 class="w-3.5 h-3.5" :stroke-width="1.5" aria-hidden="true" />
          Hours
        </span>
      </button>
      <button
        @click="activeTab = 'profitability'; if (profitabilityData.length === 0 && startDate && endDate) fetchProfitability()"
        role="tab"
        :aria-selected="activeTab === 'profitability'"
        aria-controls="tabpanel-profitability"
        id="tab-profitability"
        :tabindex="activeTab === 'profitability' ? 0 : -1"
        class="px-4 py-2 text-[0.75rem] font-medium rounded-lg transition-colors"
        :class="activeTab === 'profitability' ? 'bg-accent text-bg-base' : 'text-text-secondary hover:text-text-primary'"
      >
        <span class="flex items-center gap-1.5">
          <DollarSign class="w-3.5 h-3.5" :stroke-width="1.5" aria-hidden="true" />
          Profitability
        </span>
      </button>
      <button
        @click="switchToExpenses"
        role="tab"
        :aria-selected="activeTab === 'expenses'"
        aria-controls="tabpanel-expenses"
        id="tab-expenses"
        :tabindex="activeTab === 'expenses' ? 0 : -1"
        class="px-4 py-2 text-[0.75rem] font-medium rounded-lg transition-colors"
        :class="activeTab === 'expenses' ? 'bg-accent text-bg-base' : 'text-text-secondary hover:text-text-primary'"
      >
        <span class="flex items-center gap-1.5">
          <Receipt class="w-3.5 h-3.5" :stroke-width="1.5" aria-hidden="true" />
          Expenses
        </span>
      </button>
      <button
        @click="activeTab = 'patterns'; if (!patternsLoaded) computePatterns()"
        role="tab"
        :aria-selected="activeTab === 'patterns'"
        aria-controls="tabpanel-patterns"
        id="tab-patterns"
        :tabindex="activeTab === 'patterns' ? 0 : -1"
        class="px-4 py-2 text-[0.75rem] font-medium rounded-lg transition-colors"
        :class="activeTab === 'patterns' ? 'bg-accent text-bg-base' : 'text-text-secondary hover:text-text-primary'"
      >
        <span class="flex items-center gap-1.5">
          <Grid3x3 class="w-3.5 h-3.5" :stroke-width="1.5" aria-hidden="true" />
          Patterns
        </span>
      </button>
    </div>

    <!-- Hours Tab -->
    <template v-if="activeTab === 'hours'">
      <div id="tabpanel-hours" role="tabpanel" aria-labelledby="tab-hours" tabindex="0">
      <!-- Summary Stats - pure typography -->
      <dl class="grid grid-cols-3 gap-6 mb-4">
        <div>
          <dt class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Total Hours</dt>
          <dd class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ formatHours(filteredTotalSeconds) }}</dd>
        </div>
        <div>
          <dt class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Earnings</dt>
          <dd class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ formatCurrency(filteredTotalEarnings) }}</dd>
        </div>
        <div>
          <dt class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Projects</dt>
          <dd class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ filteredByProject.length }}</dd>
        </div>
      </dl>

      <!-- Billable split -->
      <div class="flex items-center gap-4 text-[0.75rem] text-text-secondary mb-4">
        <span>Billable: <span class="font-mono text-accent-text">{{ formatHours(billableSeconds) }}</span></span>
        <span class="text-border-subtle">|</span>
        <span>Non-billable: <span class="font-mono text-text-tertiary">{{ formatHours(nonBillableSeconds) }}</span></span>
      </div>

      <!-- Rounding impact -->
      <div v-if="roundingEnabled && roundingImpact !== 0" class="flex items-center gap-2 text-[0.75rem] text-text-secondary mb-8">
        <Clock class="w-3.5 h-3.5 text-text-tertiary shrink-0" :stroke-width="1.5" aria-hidden="true" />
        <span>Rounding {{ roundingImpact > 0 ? 'added' : 'subtracted' }}:
          <span class="font-mono text-text-primary">{{ formatRoundingHours(Math.abs(roundingImpact)) }}</span>
          across {{ roundedEntryCount }} {{ roundedEntryCount === 1 ? 'entry' : 'entries' }}
        </span>
      </div>
      <div v-else class="mb-4" />

      <!-- Chart -->
      <div class="mb-8">
        <h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">Hours by Project</h2>
        <div class="h-64" aria-label="Bar chart showing hours by project">
          <Bar v-if="chartData" :data="chartData" :options="chartOptions" />
          <div v-else class="flex flex-col items-center justify-center h-full">
            <BarChart3 class="w-12 h-12 text-text-tertiary" :stroke-width="1.5" aria-hidden="true" />
            <p class="text-sm text-text-secondary mt-3">Generate a report to see your data</p>
            <p class="text-xs text-text-tertiary mt-1">Select a date range and click Generate.</p>
            <button
              v-if="onboardingStore.isVisible"
              @click="tourStore.start(TOURS.reports)"
              class="mt-2 text-[0.6875rem] text-accent-text hover:underline"
            >
              Show me how
            </button>
          </div>
        </div>
      </div>

      <!-- Project Breakdown -->
      <div>
        <h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">Breakdown</h2>

        <div v-if="filteredByProject.length > 0">
          <div
            v-for="projectData in filteredByProject"
            :key="projectData.project_id"
            class="py-4 border-b border-border-subtle last:border-0"
          >
            <div class="flex items-center justify-between mb-2">
              <div class="flex items-center gap-3">
                <div
                  class="w-2 h-2 rounded-full shrink-0"
                  :style="{ backgroundColor: getProjectColor(projectData.project_id) }"
                  aria-hidden="true"
                />
                <span class="text-[0.8125rem] text-text-primary">{{ getProjectName(projectData.project_id) }}</span>
              </div>
              <div class="flex items-center gap-4">
                <span class="text-[0.75rem] font-mono text-accent-text">{{ formatHours(projectData.total_seconds) }}</span>
                <span class="text-[0.75rem] font-mono text-text-secondary">{{ formatCurrency((projectData.total_seconds / 3600) * getProjectRate(projectData.project_id)) }}</span>
              </div>
            </div>
            <div class="w-full bg-bg-elevated rounded-full h-[2px]">
              <div
                role="progressbar"
                :aria-valuenow="Math.round(getProjectPercentage(projectData.total_seconds))"
                aria-valuemin="0"
                aria-valuemax="100"
                :aria-label="getProjectName(projectData.project_id) + ' progress'"
                class="h-[2px] rounded-full"
                :style="{
                  width: `${getProjectPercentage(projectData.total_seconds)}%`,
                  backgroundColor: getProjectColor(projectData.project_id)
                }"
              />
            </div>
          </div>
        </div>

        <p v-else class="text-[0.75rem] text-text-tertiary py-8 text-center">
          No data for selected date range
        </p>
      </div>
      </div>
    </template>

    <!-- Profitability Tab -->
    <template v-if="activeTab === 'profitability'">
      <div id="tabpanel-profitability" role="tabpanel" aria-labelledby="tab-profitability" tabindex="0">
      <!-- Summary Stats -->
      <dl class="grid grid-cols-3 lg:grid-cols-5 gap-6 mb-4">
        <div>
          <dt class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Revenue</dt>
          <dd class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ formatCurrency(profitTotalRevenue) }}</dd>
        </div>
        <div>
          <dt class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Expenses</dt>
          <dd class="text-[1.25rem] font-[family-name:var(--font-heading)] text-status-error-text font-medium">{{ formatCurrency(profitTotalExpenses) }}</dd>
        </div>
        <div>
          <dt class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Net Profit</dt>
          <dd class="text-[1.25rem] font-[family-name:var(--font-heading)] font-medium" :class="profitTotalNet >= 0 ? 'text-status-running' : 'text-status-error-text'">{{ formatCurrency(profitTotalNet) }}</dd>
        </div>
        <div>
          <dt class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Hours</dt>
          <dd class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ formatNumber(profitTotalHours, 1) }}h</dd>
        </div>
        <div>
          <dt class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Avg Rate</dt>
          <dd class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ formatCurrency(profitAvgRate) }}</dd>
        </div>
      </dl>

      <!-- Revenue Chart -->
      <div class="mb-8">
        <h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">Revenue by Project</h2>
        <div class="h-64" aria-label="Horizontal bar chart showing revenue by project">
          <Bar v-if="profitChartData" :data="profitChartData" :options="profitChartOptions" />
          <div v-else class="flex flex-col items-center justify-center h-full">
            <DollarSign class="w-12 h-12 text-text-tertiary" :stroke-width="1.5" aria-hidden="true" />
            <p class="text-sm text-text-secondary mt-3">Generate a report to see profitability data</p>
            <p class="text-xs text-text-tertiary mt-1">Select a date range and click Generate.</p>
          </div>
        </div>
      </div>

      <!-- Project Table -->
      <div>
        <h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">Per-Project Breakdown</h2>

        <div v-if="profitabilityData.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">Project</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-right text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium">Hours</th>
                <th class="px-4 py-3 text-right text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium">Rate</th>
                <th class="px-4 py-3 text-right text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium">Revenue</th>
                <th class="px-4 py-3 text-right text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium">Expenses</th>
                <th class="px-4 py-3 text-right text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium">Net Profit</th>
                <th class="px-4 py-3 text-right text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium">Budget %</th>
              </tr>
            </thead>
            <tbody>
              <tr
                v-for="row in profitabilityData"
                :key="row.project_name"
                class="border-b border-border-subtle last:border-0"
              >
                <td class="px-4 py-3 text-[0.8125rem] text-text-primary">{{ row.project_name }}</td>
                <td class="px-4 py-3 text-[0.75rem] text-text-secondary">{{ row.client_name || '-' }}</td>
                <td class="px-4 py-3 text-right text-[0.75rem] font-mono text-text-primary">{{ formatNumber(row.total_hours, 1) }}h</td>
                <td class="px-4 py-3 text-right text-[0.75rem] font-mono text-text-secondary">{{ formatCurrency(row.hourly_rate) }}</td>
                <td class="px-4 py-3 text-right text-[0.75rem] font-mono text-accent-text">{{ formatCurrency(row.revenue) }}</td>
                <td class="px-4 py-3 text-right text-[0.75rem] font-mono text-text-secondary">{{ row.expenses > 0 ? formatCurrency(row.expenses) : '-' }}</td>
                <td class="px-4 py-3 text-right text-[0.75rem] font-mono" :class="row.net_profit >= 0 ? 'text-status-running' : 'text-status-error-text'">{{ formatCurrency(row.net_profit) }}</td>
                <td class="px-4 py-3 text-right text-[0.75rem] font-mono" :class="row.budget_used_pct != null && row.budget_used_pct > 100 ? 'text-status-error-text' : 'text-text-secondary'">
                  {{ row.budget_used_pct != null ? formatNumber(row.budget_used_pct, 0) + '%' : '-' }}
                </td>
              </tr>
            </tbody>
          </table>
        </div>

        <p v-else class="text-[0.75rem] text-text-tertiary py-8 text-center">
          No data for selected date range
        </p>
      </div>
      </div>
    </template>

    <!-- Patterns Tab -->
    <template v-if="activeTab === 'patterns'">
      <div id="tabpanel-patterns" role="tabpanel" aria-labelledby="tab-patterns" tabindex="0" class="space-y-6">
        <!-- Summary stats -->
        <div v-if="patternsLoaded && hasPatternData" class="flex items-center gap-6 text-[0.75rem] text-text-secondary">
          <span v-if="peakDay">Most productive: <strong class="text-text-primary">{{ peakDay }}</strong></span>
          <span v-if="peakHour">Peak hour: <strong class="text-text-primary">{{ peakHour }}</strong></span>
        </div>

        <!-- View toggle -->
        <div v-if="patternsLoaded && hasPatternData" class="flex items-center gap-2">
          <button
            @click="heatmapViewMode = 'grid'"
            :class="heatmapViewMode === 'grid' ? 'bg-accent text-bg-base' : 'text-text-secondary hover:text-text-primary'"
            class="px-3 py-1 text-[0.6875rem] rounded-lg transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent"
          >
            Grid
          </button>
          <button
            @click="heatmapViewMode = 'table'"
            :class="heatmapViewMode === 'table' ? 'bg-accent text-bg-base' : 'text-text-secondary hover:text-text-primary'"
            class="px-3 py-1 text-[0.6875rem] rounded-lg transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent"
          >
            Data Table
          </button>
        </div>

        <!-- Grid view -->
        <div v-if="patternsLoaded && hasPatternData && heatmapViewMode === 'grid'" class="overflow-x-auto">
          <div class="inline-grid gap-0.5" :style="{ gridTemplateColumns: 'auto repeat(24, minmax(2rem, 1fr))' }" role="grid" aria-label="Time-of-day activity heatmap">
            <!-- Header row -->
            <div class="p-1" role="columnheader"></div>
            <div v-for="h in 24" :key="'h-' + h" class="p-1 text-[0.5625rem] text-text-tertiary text-center" role="columnheader">
              {{ h - 1 }}
            </div>
            <!-- Data rows -->
            <template v-for="(dayData, dayIdx) in heatmapData" :key="'d-' + dayIdx">
              <div class="p-1 text-[0.625rem] text-text-secondary" role="rowheader">
                {{ dayNames[dayIdx] }}
              </div>
              <div
                v-for="(value, hourIdx) in dayData"
                :key="'c-' + dayIdx + '-' + hourIdx"
                role="gridcell"
                :aria-label="dayNames[dayIdx] + ' ' + hourIdx + ':00 - ' + (value > 0 ? formatNumber(value, 1) + ' hours' : 'no activity')"
                class="p-1 text-center text-[0.5625rem] rounded-sm transition-colors"
                :style="{ backgroundColor: getHeatColor(value) }"
                :class="value > 0 ? 'text-text-primary' : 'text-transparent'"
              >
                {{ value > 0 ? formatNumber(value, 1) : '' }}
              </div>
            </template>
          </div>
        </div>

        <!-- Table view -->
        <div v-if="patternsLoaded && hasPatternData && heatmapViewMode === 'table'" class="overflow-x-auto">
          <table class="w-full text-[0.6875rem]">
            <thead>
              <tr class="border-b border-border-subtle">
                <th scope="col" class="px-2 py-1 text-left text-text-tertiary">Day</th>
                <th v-for="h in 24" :key="h" scope="col" class="px-1 py-1 text-center text-text-tertiary">{{ h - 1 }}</th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="(dayData, dayIdx) in heatmapData" :key="dayIdx" class="border-b border-border-subtle">
                <th scope="row" class="px-2 py-1 text-left text-text-secondary">{{ dayNames[dayIdx] }}</th>
                <td v-for="(value, hourIdx) in dayData" :key="hourIdx" class="px-1 py-1 text-center"
                  :class="value > 0 ? 'text-accent-text' : 'text-text-tertiary'">
                  {{ value > 0 ? formatNumber(value, 1) : '-' }}
                </td>
              </tr>
            </tbody>
          </table>
        </div>

        <!-- Empty state -->
        <div v-if="patternsLoaded && !hasPatternData" class="py-12 text-center">
          <Grid3x3 class="w-12 h-12 text-text-tertiary mx-auto animate-float mb-4" :stroke-width="1.5" aria-hidden="true" />
          <p class="text-[0.8125rem] text-text-secondary">No time data for the selected period</p>
        </div>

        <!-- Loading state before patterns computed -->
        <div v-if="!patternsLoaded" class="py-12 text-center">
          <Grid3x3 class="w-12 h-12 text-text-tertiary mx-auto animate-float mb-4" :stroke-width="1.5" aria-hidden="true" />
          <p class="text-[0.8125rem] text-text-secondary">Select a date range and click Generate to see patterns</p>
        </div>
      </div>
    </template>

    <!-- Expenses Tab -->
    <template v-if="activeTab === 'expenses'">
      <div id="tabpanel-expenses" role="tabpanel" aria-labelledby="tab-expenses" tabindex="0">
      <!-- Summary Stats -->
      <dl class="grid grid-cols-3 gap-6 mb-4">
        <div>
          <dt class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Total Expenses</dt>
          <dd class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ formatCurrency(expTotalAmount) }}</dd>
        </div>
        <div>
          <dt class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Number of Expenses</dt>
          <dd class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ expensesData.length }}</dd>
        </div>
        <div>
          <dt class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Top Category</dt>
          <dd class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium capitalize">{{ expTopCategory || '-' }}</dd>
        </div>
      </dl>

      <!-- Invoiced vs un-invoiced split -->
      <div class="flex items-center gap-4 text-[0.75rem] text-text-secondary mb-8">
        <span>Invoiced: <span class="font-mono text-accent-text">{{ formatCurrency(expInvoicedAmount) }}</span></span>
        <span class="text-border-subtle">|</span>
        <span>Un-invoiced: <span class="font-mono text-text-tertiary">{{ formatCurrency(expUninvoicedAmount) }}</span></span>
      </div>

      <!-- By Category Breakdown -->
      <div class="mb-8">
        <h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">Expenses by Category</h2>

        <div v-if="expByCategory.length > 0">
          <div
            v-for="cat in expByCategory"
            :key="cat.category"
            class="py-4 border-b border-border-subtle last:border-0"
          >
            <div class="flex items-center justify-between mb-2">
              <span class="text-[0.8125rem] text-text-primary capitalize">{{ cat.category }}</span>
              <div class="flex items-center gap-4">
                <span class="text-[0.75rem] font-mono text-accent-text">{{ formatCurrency(cat.amount) }}</span>
                <span class="text-[0.75rem] font-mono text-text-tertiary w-12 text-right">{{ formatNumber(cat.percentage, 0) }}%</span>
              </div>
            </div>
            <div class="w-full bg-bg-elevated rounded-full h-[2px]">
              <div
                role="progressbar"
                :aria-valuenow="Math.round(cat.percentage)"
                aria-valuemin="0"
                aria-valuemax="100"
                :aria-label="cat.category + ' expense percentage'"
                class="h-[2px] rounded-full bg-accent"
                :style="{ width: `${cat.percentage}%` }"
              />
            </div>
          </div>
        </div>

        <p v-else class="text-[0.75rem] text-text-tertiary py-8 text-center">
          No expense data for selected date range
        </p>
      </div>

      <!-- By Project Breakdown -->
      <div>
        <h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">Expenses by Project</h2>

        <div v-if="expByProject.length > 0">
          <div
            v-for="proj in expByProject"
            :key="proj.project_id"
            class="py-4 border-b border-border-subtle last:border-0"
          >
            <div class="flex items-center justify-between mb-2">
              <div class="flex items-center gap-3">
                <div
                  class="w-2 h-2 rounded-full shrink-0"
                  :style="{ backgroundColor: getProjectColor(proj.project_id) }"
                  aria-hidden="true"
                />
                <span class="text-[0.8125rem] text-text-primary">{{ getProjectName(proj.project_id) }}</span>
              </div>
              <div class="flex items-center gap-4">
                <span class="text-[0.75rem] font-mono text-accent-text">{{ formatCurrency(proj.amount) }}</span>
                <span class="text-[0.75rem] font-mono text-text-tertiary w-12 text-right">{{ formatNumber(proj.percentage, 0) }}%</span>
              </div>
            </div>
            <div class="w-full bg-bg-elevated rounded-full h-[2px]">
              <div
                role="progressbar"
                :aria-valuenow="Math.round(proj.percentage)"
                aria-valuemin="0"
                aria-valuemax="100"
                :aria-label="getProjectName(proj.project_id) + ' expense percentage'"
                class="h-[2px] rounded-full"
                :style="{
                  width: `${proj.percentage}%`,
                  backgroundColor: getProjectColor(proj.project_id)
                }"
              />
            </div>
          </div>
        </div>

        <p v-else class="text-[0.75rem] text-text-tertiary py-8 text-center">
          No expense data for selected date range
        </p>
      </div>
      </div>
    </template>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, watch, nextTick } from 'vue'
import { invoke } from '@tauri-apps/api/core'
import { Bar } from 'vue-chartjs'
import { BarChart3, DollarSign, Receipt, Grid3x3, Clock } from 'lucide-vue-next'
import AppDatePicker from '../components/AppDatePicker.vue'
import AppDateRangePresets from '../components/AppDateRangePresets.vue'
import AppSelect from '../components/AppSelect.vue'
import { useToastStore } from '../stores/toast'
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  BarElement,
  Title,
  Tooltip,
  Legend
} from 'chart.js'
import { useEntriesStore } from '../stores/entries'
import { useExpensesStore, type Expense } from '../stores/expenses'
import { useProjectsStore } from '../stores/projects'
import { useSettingsStore } from '../stores/settings'
import { formatCurrency, formatNumber } from '../utils/locale'
import { getChartTheme, buildBarChartOptions } from '../utils/chartTheme'
import { useOnboardingStore } from '../stores/onboarding'
import { useTourStore } from '../stores/tour'
import { TOURS } from '../utils/tours'
import { save } from '@tauri-apps/plugin-dialog'
import {
  generateHoursReportPdf,
  generateProfitabilityReportPdf,
  generateExpensesReportPdf,
  generatePatternsReportPdf,
  type HoursReportData,
  type ProfitabilityReportData,
  type ExpenseReportData,
  type PatternsReportData,
} from '../utils/reportPdf'

// Register Chart.js components
ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend)

const entriesStore = useEntriesStore()
const expensesStore = useExpensesStore()
const projectsStore = useProjectsStore()
const toastStore = useToastStore()
const settingsStore = useSettingsStore()
const onboardingStore = useOnboardingStore()
const tourStore = useTourStore()

interface ProjectReport {
  project_id: number
  total_seconds: number
}

interface ReportData {
  totalSeconds: number
  totalEarnings?: number
  byProject: ProjectReport[]
}

interface ProfitabilityRow {
  project_name: string
  client_name: string | null
  total_hours: number
  hourly_rate: number
  revenue: number
  budget_hours: number | null
  budget_used_pct: number | null
  expenses: number
  net_profit: number
}

const activeTab = ref<'hours' | 'profitability' | 'expenses' | 'patterns'>('hours')
const profitabilityData = ref<ProfitabilityRow[]>([])
const expensesData = ref<Expense[]>([])

function onTabKeydown(e: KeyboardEvent) {
  const tabs: Array<'hours' | 'profitability' | 'expenses' | 'patterns'> = ['hours', 'profitability', 'expenses', 'patterns']
  const current = tabs.indexOf(activeTab.value)
  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
  }
  activeTab.value = tabs[next]
  if (tabs[next] === 'profitability' && profitabilityData.value.length === 0 && startDate.value && endDate.value) {
    fetchProfitability()
  }
  if (tabs[next] === 'expenses' && expensesData.value.length === 0 && startDate.value && endDate.value) {
    fetchExpensesReport()
  }
  if (tabs[next] === 'patterns' && !patternsLoaded.value) {
    computePatterns()
  }
  const nextTabEl = document.getElementById(`tab-${tabs[next]}`)
  nextTabEl?.focus()
}

function switchToExpenses() {
  activeTab.value = 'expenses'
  if (expensesData.value.length === 0 && startDate.value && endDate.value) {
    fetchExpensesReport()
  }
}

const billableFilter = ref<string>('all')
const billableFilterOptions = [
  { label: 'All entries', value: 'all' },
  { label: 'Billable only', value: 'billable' },
  { label: 'Non-billable only', value: 'non-billable' },
]

const startDate = ref('')
const endDate = ref('')
const reportData = ref<ReportData>({
  totalSeconds: 0,
  totalEarnings: 0,
  byProject: []
})

// Billable split totals computed from entries
const billableSeconds = computed(() => {
  return entriesStore.entries
    .filter(e => (e.billable ?? 1) === 1)
    .reduce((sum, e) => sum + e.duration, 0)
})
const nonBillableSeconds = computed(() => {
  return entriesStore.entries
    .filter(e => e.billable === 0)
    .reduce((sum, e) => sum + e.duration, 0)
})

// Rounding impact helpers
function roundDuration(seconds: number, increment: number, method: string): number {
  const incrementSeconds = increment * 60
  if (incrementSeconds <= 0) return seconds
  if (method === 'up') return Math.ceil(seconds / incrementSeconds) * incrementSeconds
  if (method === 'down') return Math.floor(seconds / incrementSeconds) * incrementSeconds
  return Math.round(seconds / incrementSeconds) * incrementSeconds
}

const roundingEnabled = computed(() => settingsStore.settings.rounding_enabled === 'true')
const roundedEntryCount = ref(0)

const roundingImpact = computed(() => {
  if (!roundingEnabled.value) return 0
  const increment = parseInt(settingsStore.settings.rounding_increment) || 0
  const method = settingsStore.settings.rounding_method || 'nearest'
  if (increment <= 0) return 0

  let totalDiff = 0
  let count = 0
  for (const entry of entriesStore.entries) {
    const rounded = roundDuration(entry.duration, increment, method)
    if (rounded !== entry.duration) {
      totalDiff += rounded - entry.duration
      count++
    }
  }
  roundedEntryCount.value = count
  return totalDiff
})

function formatRoundingHours(seconds: number): string {
  const h = Math.floor(seconds / 3600)
  const m = Math.floor((seconds % 3600) / 60)
  if (h > 0 && m > 0) return `${h}h ${m}m`
  if (h > 0) return `${h}h`
  return `${m}m`
}

// Filtered report data based on billable filter
const filteredByProject = computed(() => {
  if (billableFilter.value === 'all') return reportData.value.byProject || []

  const isBillable = billableFilter.value === 'billable'
  const filteredEntries = entriesStore.entries.filter(e =>
    isBillable ? (e.billable ?? 1) === 1 : e.billable === 0
  )

  const projectMap = new Map<number, number>()
  for (const e of filteredEntries) {
    projectMap.set(e.project_id, (projectMap.get(e.project_id) || 0) + e.duration)
  }

  return Array.from(projectMap.entries()).map(([project_id, total_seconds]) => ({
    project_id,
    total_seconds,
  }))
})

const filteredTotalSeconds = computed(() => {
  if (billableFilter.value === 'all') return reportData.value.totalSeconds
  return filteredByProject.value.reduce((sum, p) => sum + p.total_seconds, 0)
})

const filteredTotalEarnings = computed(() => {
  if (billableFilter.value === 'all') return reportData.value.totalEarnings || 0
  return filteredByProject.value.reduce((sum, p) => {
    const rate = getProjectRate(p.project_id)
    return sum + (p.total_seconds / 3600) * rate
  }, 0)
})

// Total hours for percentage calculation
const totalHours = computed(() => {
  return filteredTotalSeconds.value / 3600
})

// Get project percentage
function getProjectPercentage(projectSeconds: number): number {
  if (totalHours.value === 0) return 0
  return (projectSeconds / 3600 / totalHours.value) * 100
}

// Chart theme state
const chartTheme = ref(getChartTheme())

function refreshChartTheme() {
  chartTheme.value = getChartTheme()
}

// Chart data
const chartData = computed(() => {
  if (filteredByProject.value.length === 0) {
    return null
  }

  const labels = filteredByProject.value.map(p => getProjectName(p.project_id))
  const data = filteredByProject.value.map(p => p.total_seconds / 3600)
  const colors = filteredByProject.value.map(p => getProjectColor(p.project_id))

  return {
    labels,
    datasets: [
      {
        label: 'Hours',
        data,
        backgroundColor: colors,
        borderRadius: 2
      }
    ]
  }
})

// Chart options (theme-aware)
const chartOptions = computed(() => {
  const theme = chartTheme.value
  const base = buildBarChartOptions(theme)
  return {
    ...base,
    scales: {
      ...base.scales,
      y: {
        ...base.scales.y,
        beginAtZero: true,
      },
    },
    plugins: {
      ...base.plugins,
      tooltip: {
        ...base.plugins.tooltip,
        callbacks: {
          label: (context: { raw: unknown }) => {
            const hours = context.raw as number
            return `${formatNumber(hours, 1)} hours`
          }
        }
      }
    }
  }
})

// Format hours
function formatHours(seconds: number): string {
  const hours = Math.floor(seconds / 3600)
  const minutes = Math.floor((seconds % 3600) / 60)
  if (hours > 0) {
    return `${hours}h ${minutes}m`
  }
  return `${minutes}m`
}

// Get project name by ID
function getProjectName(projectId: number): string {
  const project = projectsStore.projects.find(p => p.id === projectId)
  return project?.name || 'Unknown Project'
}

// Get project color by ID
function getProjectColor(projectId: number): string {
  const project = projectsStore.projects.find(p => p.id === projectId)
  return project?.color || '#6B7280'
}

// Get project hourly rate
function getProjectRate(projectId: number): number {
  const project = projectsStore.projects.find(p => p.id === projectId)
  return project?.hourly_rate || 0
}

// Fetch report data
async function fetchReport() {
  if (!startDate.value || !endDate.value) {
    toastStore.info('Please select a date range')
    return
  }

  try {
    // Reset patterns when fetching new report
    patternsLoaded.value = false

    // Fetch entries for billable split calculations
    await entriesStore.fetchEntries(startDate.value, endDate.value)

    const data = await invoke<{ totalSeconds: number; byProject: unknown[] }>('get_reports', {
      startDate: startDate.value,
      endDate: endDate.value
    })

    // Calculate total earnings
    let totalEarnings = 0
    if (data.byProject && Array.isArray(data.byProject)) {
      (data.byProject as ProjectReport[]).forEach((p: ProjectReport) => {
        const rate = getProjectRate(p.project_id)
        totalEarnings += (p.total_seconds / 3600) * rate
      })
    }

    reportData.value = {
      totalSeconds: data.totalSeconds,
      totalEarnings,
      byProject: data.byProject as ProjectReport[]
    }

    // Also fetch profitability if on that tab
    if (activeTab.value === 'profitability') {
      await fetchProfitability()
    }

    // Also fetch expenses if on that tab
    if (activeTab.value === 'expenses') {
      await fetchExpensesReport()
    }

    // Also recompute patterns if on that tab
    if (activeTab.value === 'patterns') {
      computePatterns()
    }
  } catch (error) {
    console.error('Failed to fetch report:', error)
    toastStore.error('Failed to generate report')
  }
}

// Profitability summary stats
const profitTotalRevenue = computed(() => profitabilityData.value.reduce((sum, r) => sum + r.revenue, 0))
const profitTotalExpenses = computed(() => profitabilityData.value.reduce((sum, r) => sum + (r.expenses || 0), 0))
const profitTotalNet = computed(() => profitabilityData.value.reduce((sum, r) => sum + (r.net_profit ?? r.revenue), 0))
const profitTotalHours = computed(() => profitabilityData.value.reduce((sum, r) => sum + r.total_hours, 0))
const profitAvgRate = computed(() => profitTotalHours.value > 0 ? profitTotalRevenue.value / profitTotalHours.value : 0)

// Profitability chart data
const profitChartData = computed(() => {
  if (profitabilityData.value.length === 0) return null

  const labels = profitabilityData.value.map(r => r.project_name)
  const data = profitabilityData.value.map(r => r.revenue)
  const colors = profitabilityData.value.map((r) => {
    const project = projectsStore.projects.find(p => p.name === r.project_name)
    return project?.color || '#6B7280'
  })

  return {
    labels,
    datasets: [
      {
        label: 'Revenue',
        data,
        backgroundColor: colors,
        borderRadius: 2
      }
    ]
  }
})

// Profitability chart options (theme-aware)
const profitChartOptions = computed(() => {
  const theme = chartTheme.value
  const base = buildBarChartOptions(theme)
  return {
    ...base,
    indexAxis: 'y' as const,
    scales: {
      x: {
        beginAtZero: true,
        ticks: { color: theme.textTertiary, font: { size: 11 } },
        grid: { color: theme.gridColor },
        border: { display: false },
      },
      y: {
        ticks: { color: theme.textTertiary, font: { size: 11 } },
        grid: { display: false },
        border: { display: false },
      },
    },
    plugins: {
      ...base.plugins,
      tooltip: {
        ...base.plugins.tooltip,
        callbacks: {
          label: (context: { raw: unknown }) => {
            const val = context.raw as number
            return formatCurrency(val)
          }
        }
      }
    }
  }
})

// Fetch profitability data
async function fetchProfitability() {
  if (!startDate.value || !endDate.value) {
    toastStore.info('Please select a date range')
    return
  }

  try {
    profitabilityData.value = await invoke<ProfitabilityRow[]>('get_profitability_report', {
      startDate: startDate.value,
      endDate: endDate.value
    })
  } catch (error) {
    console.error('Failed to fetch profitability report:', error)
    toastStore.error('Failed to generate profitability report')
  }
}

// =============================================
// EXPENSES TAB
// =============================================

// Fetch expenses for report
async function fetchExpensesReport() {
  if (!startDate.value || !endDate.value) return

  try {
    await expensesStore.fetchExpenses(undefined, startDate.value, endDate.value)
    expensesData.value = [...expensesStore.expenses]
  } catch (error) {
    console.error('Failed to fetch expenses for report:', error)
  }
}

// Expense summary computeds
const expTotalAmount = computed(() => {
  return expensesData.value.reduce((sum, e) => sum + e.amount, 0)
})

const expInvoicedAmount = computed(() => {
  return expensesData.value.filter(e => e.invoiced).reduce((sum, e) => sum + e.amount, 0)
})

const expUninvoicedAmount = computed(() => {
  return expensesData.value.filter(e => !e.invoiced).reduce((sum, e) => sum + e.amount, 0)
})

const expTopCategory = computed(() => {
  if (expensesData.value.length === 0) return ''
  const catMap = new Map<string, number>()
  for (const e of expensesData.value) {
    catMap.set(e.category, (catMap.get(e.category) || 0) + e.amount)
  }
  let topCat = ''
  let topAmount = 0
  for (const [cat, amount] of catMap) {
    if (amount > topAmount) {
      topCat = cat
      topAmount = amount
    }
  }
  return topCat
})

// By category breakdown
const expByCategory = computed(() => {
  if (expensesData.value.length === 0) return []
  const total = expTotalAmount.value
  if (total === 0) return []

  const catMap = new Map<string, number>()
  for (const e of expensesData.value) {
    catMap.set(e.category, (catMap.get(e.category) || 0) + e.amount)
  }

  return Array.from(catMap.entries())
    .map(([category, amount]) => ({
      category,
      amount,
      percentage: (amount / total) * 100
    }))
    .sort((a, b) => b.amount - a.amount)
})

// By project breakdown
const expByProject = computed(() => {
  if (expensesData.value.length === 0) return []
  const total = expTotalAmount.value
  if (total === 0) return []

  const projMap = new Map<number, number>()
  for (const e of expensesData.value) {
    projMap.set(e.project_id, (projMap.get(e.project_id) || 0) + e.amount)
  }

  return Array.from(projMap.entries())
    .map(([project_id, amount]) => ({
      project_id,
      amount,
      percentage: (amount / total) * 100
    }))
    .sort((a, b) => b.amount - a.amount)
})

// =============================================
// PATTERNS TAB
// =============================================

const dayNames = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
const heatmapData = ref<number[][]>([])
const patternsLoaded = ref(false)
const heatmapViewMode = ref<'grid' | 'table'>('grid')

const hasPatternData = computed(() => heatmapData.value.some(row => row.some(v => v > 0)))

const peakDay = computed(() => {
  if (!heatmapData.value.length) return null
  const totals = heatmapData.value.map(row => row.reduce((a, b) => a + b, 0))
  const maxVal = Math.max(...totals)
  const maxIdx = totals.indexOf(maxVal)
  return maxVal > 0 ? dayNames[maxIdx] : null
})

const peakHour = computed(() => {
  if (!heatmapData.value.length) return null
  let maxVal = 0
  let maxHour = 0
  for (const row of heatmapData.value) {
    for (let h = 0; h < 24; h++) {
      if (row[h] > maxVal) {
        maxVal = row[h]
        maxHour = h
      }
    }
  }
  return maxVal > 0 ? `${maxHour}:00` : null
})

function computePatterns() {
  const grid: number[][] = Array.from({ length: 7 }, () => Array(24).fill(0))

  for (const entry of entriesStore.entries) {
    if (!entry.start_time) continue
    const d = new Date(entry.start_time)
    const jsDay = d.getDay()
    const day = jsDay === 0 ? 6 : jsDay - 1 // Mon=0, Sun=6
    const hour = d.getHours()
    grid[day][hour] += entry.duration / 3600
  }

  heatmapData.value = grid
  patternsLoaded.value = true
}

function getHeatColor(value: number): string {
  if (value === 0) return 'transparent'
  const maxVal = Math.max(...heatmapData.value.flat(), 1)
  const intensity = Math.min(value / maxVal, 1)
  const alpha = 0.1 + intensity * 0.6
  return `rgba(245, 158, 11, ${alpha})`
}

// Export to CSV
function exportCSV() {
  if (!reportData.value.byProject || reportData.value.byProject.length === 0) {
    toastStore.info('No data to export')
    return
  }

  // CSV header
  let csv = 'Project,Hours,Rate,Earnings\n'

  // Add rows
  reportData.value.byProject.forEach((p: ProjectReport) => {
    const name = getProjectName(p.project_id)
    const hours = (p.total_seconds / 3600).toFixed(2)
    const rate = getProjectRate(p.project_id)
    const rateFixed = rate.toFixed(2)
    const earnings = ((p.total_seconds / 3600) * rate).toFixed(2)
    csv += `"${name}",${hours},${rateFixed},${earnings}\n`
  })

  // Add totals
  csv += `\nTotal,${(reportData.value.totalSeconds / 3600).toFixed(2)},,${reportData.value.totalEarnings?.toFixed(2) || '0.00'}\n`

  // Download file
  const blob = new Blob([csv], { type: 'text/csv' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = `time-report-${startDate.value}-to-${endDate.value}.csv`
  a.click()
  URL.revokeObjectURL(url)
}

// Export to PDF
async function exportPDF() {
  try {
    let doc
    const dateRange = { start: startDate.value, end: endDate.value }

    if (activeTab.value === 'hours') {
      if (!reportData.value.byProject || reportData.value.byProject.length === 0) {
        toastStore.info('No data to export')
        return
      }
      const data: HoursReportData = {
        dateRange,
        totalHours: filteredTotalSeconds.value / 3600,
        totalEarnings: filteredTotalEarnings.value,
        billableHours: billableSeconds.value / 3600,
        nonBillableHours: nonBillableSeconds.value / 3600,
        projects: filteredByProject.value.map((p: ProjectReport) => ({
          name: getProjectName(p.project_id),
          color: getProjectColor(p.project_id),
          hours: p.total_seconds / 3600,
          rate: getProjectRate(p.project_id),
          earnings: (p.total_seconds / 3600) * getProjectRate(p.project_id),
          percentage: getProjectPercentage(p.total_seconds),
        })),
      }
      doc = generateHoursReportPdf(data)
    } else if (activeTab.value === 'profitability') {
      if (profitabilityData.value.length === 0) {
        toastStore.info('No data to export')
        return
      }
      const data: ProfitabilityReportData = {
        dateRange,
        totalRevenue: profitTotalRevenue.value,
        totalExpenses: profitTotalExpenses.value,
        totalNet: profitTotalNet.value,
        totalHours: profitTotalHours.value,
        avgRate: profitAvgRate.value,
        rows: profitabilityData.value,
      }
      doc = generateProfitabilityReportPdf(data)
    } else if (activeTab.value === 'expenses') {
      if (expensesData.value.length === 0) {
        toastStore.info('No data to export')
        return
      }
      const data: ExpenseReportData = {
        dateRange,
        totalAmount: expTotalAmount.value,
        invoicedAmount: expInvoicedAmount.value,
        uninvoicedAmount: expUninvoicedAmount.value,
        byCategory: expByCategory.value,
        byProject: expByProject.value.map(p => ({
          name: getProjectName(p.project_id),
          color: getProjectColor(p.project_id),
          amount: p.amount,
          percentage: p.percentage,
        })),
      }
      doc = generateExpensesReportPdf(data)
    } else {
      if (!hasPatternData.value) {
        toastStore.info('No data to export')
        return
      }
      const data: PatternsReportData = {
        dateRange,
        heatmap: heatmapData.value,
        peakDay: peakDay.value || '-',
        peakHour: peakHour.value || '-',
      }
      doc = generatePatternsReportPdf(data)
    }

    const tabName = activeTab.value
    const filePath = await save({
      defaultPath: `${tabName}-report-${startDate.value}-to-${endDate.value}.pdf`,
      filters: [{ name: 'PDF', extensions: ['pdf'] }],
    })
    if (!filePath) return

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

// Recreate charts on theme or accent change
watch(() => settingsStore.settings.theme_mode, () => {
  nextTick(() => { refreshChartTheme() })
})
watch(() => settingsStore.settings.accent_color, () => {
  nextTick(() => { refreshChartTheme() })
})

// Set default dates on mount
onMounted(async () => {
  await Promise.all([
    projectsStore.fetchProjects(),
    entriesStore.fetchEntries(),
    settingsStore.fetchSettings(),
  ])

  refreshChartTheme()

  // Set default to this month
  const now = new Date()
  const monthStart = new Date(now.getFullYear(), now.getMonth(), 1)
  startDate.value = monthStart.toISOString().split('T')[0]
  endDate.value = now.toISOString().split('T')[0]

  // Fetch initial report
  fetchReport()
})
</script>
