<template>
  <div class="bg-neutral rounded-lg p-4 sm:p-6">
    <!-- Controls -->
    <div class="flex flex-wrap items-end gap-4 mb-6">
      <div>
        <label class="label pb-1">
          <span class="label-text font-semibold">Compare Years</span>
        </label>
        <YearSelector v-model="selectedYears" />
      </div>
      <div class="ml-auto self-end">
        <ExportButtons :data="exportData" filename="customer-signups-weekly" />
      </div>
    </div>

    <!-- Loading -->
    <div v-if="loading" class="flex justify-center items-center h-[400px]">
      <span class="loading loading-spinner loading-lg"></span>
    </div>

    <!-- Error -->
    <div v-else-if="error" class="alert alert-error">
      <svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24">
        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
      </svg>
      <span>{{ error }}</span>
      <button class="btn btn-sm" @click="fetchData">Retry</button>
    </div>

    <!-- Chart -->
    <div v-else class="w-full h-[420px] relative">
      <Bar v-if="chartData" :data="chartData as any" :options="chartOptions as any" />
      <div v-else class="flex items-center justify-center h-full text-base-content/50">
        No signup data available for the selected years.
      </div>
    </div>

    <!-- Summary stats -->
    <div v-if="!loading && !error" class="grid grid-cols-2 sm:grid-cols-4 gap-4 mt-6">
      <div
        v-for="(stat, index) in summaryStats"
        :key="stat.year"
        class="stat bg-base-100 rounded-lg p-3"
      >
        <div class="stat-title text-sm">{{ stat.year }} Total</div>
        <div class="stat-value text-lg" :style="{ color: yearColors[index % yearColors.length].border }">
          {{ stat.totalSignups.toLocaleString() }}
        </div>
        <div class="stat-desc">new customers</div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue';
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  BarElement,
  Title,
  Tooltip,
  Legend
} from 'chart.js';
import { Bar } from 'vue-chartjs';
import YearSelector from './components/YearSelector.vue';
import ExportButtons from './components/ExportButtons.vue';
import { statsService } from '../../services/statsService';
import type { WeeklyCustomerYearData } from '../../types/stats';

ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend);

const currentYear = new Date().getFullYear();

const selectedYears = ref<number[]>([currentYear, currentYear - 1]);
const loading = ref(false);
const error = ref<string | null>(null);
const weeklyData = ref<WeeklyCustomerYearData[]>([]);

const yearColors = [
  { border: 'rgb(59, 130, 246)',  background: 'rgba(59, 130, 246, 0.7)' },
  { border: 'rgb(16, 185, 129)',  background: 'rgba(16, 185, 129, 0.7)' },
  { border: 'rgb(249, 115, 22)',  background: 'rgba(249, 115, 22, 0.7)' },
  { border: 'rgb(139, 92, 246)', background: 'rgba(139, 92, 246, 0.7)' },
];

// Month label at the approximate ISO week that starts each month
const MONTH_AT_WEEK: Record<number, string> = {
  1: 'Jan', 5: 'Feb', 9: 'Mar', 14: 'Apr', 18: 'May', 22: 'Jun',
  27: 'Jul', 31: 'Aug', 36: 'Sep', 40: 'Oct', 44: 'Nov', 48: 'Dec'
};

const xLabels = Array.from({ length: 52 }, (_, i) => MONTH_AT_WEEK[i + 1] ?? '');

const chartData = computed(() => {
  if (weeklyData.value.length === 0) return null;

  const datasets = weeklyData.value.map((yearData, index) => {
    const slots = new Array<number>(52).fill(0);
    for (const pt of yearData.data) {
      const idx = (pt.week_number ?? 0) - 1;
      if (idx >= 0 && idx < 52) slots[idx] = pt.signups;
    }
    const color = yearColors[index % yearColors.length];
    return {
      label: String(yearData.year),
      data: slots,
      backgroundColor: color.background,
      borderColor: color.border,
      borderWidth: 1,
      borderRadius: 3,
    };
  });

  return { labels: xLabels, datasets };
});

const chartOptions = computed(() => ({
  responsive: true,
  maintainAspectRatio: false,
  interaction: { mode: 'index' as const, intersect: false },
  plugins: {
    title: {
      display: true,
      text: 'New Customer Sign-ups — Full Year (Weekly)',
      font: { size: 16 },
    },
    legend: { position: 'top' as const },
    tooltip: {
      callbacks: {
        title: (items: any[]) => `Week ${items[0]?.dataIndex + 1}`,
        label: (ctx: any) => {
          const v = ctx.parsed?.y ?? 0;
          return `${ctx.dataset.label}: ${v} new customer${v !== 1 ? 's' : ''}`;
        },
      },
    },
  },
  scales: {
    x: {
      grid: { display: false },
      ticks: {
        autoSkip: false,
        maxRotation: 0,
        callback: (_val: any, index: number) => xLabels[index] || null,
      },
    },
    y: {
      beginAtZero: true,
      title: { display: true, text: 'New Customers' },
      ticks: {
        stepSize: 1,
        callback: (v: string | number) =>
          typeof v === 'number' && Number.isInteger(v) ? v : '',
      },
    },
  },
}));

const summaryStats = computed(() =>
  weeklyData.value.map(yd => ({
    year: yd.year,
    totalSignups: yd.data.reduce((s, d) => s + d.signups, 0),
  }))
);

const exportData = computed(() => {
  const rows: Record<string, unknown>[] = [];
  weeklyData.value.forEach(yd =>
    yd.data.forEach(d =>
      rows.push({
        year: yd.year,
        week_number: d.week_number,
        week_start: d.week_start,
        signups: d.signups,
      })
    )
  );
  return rows;
});

async function fetchData() {
  loading.value = true;
  error.value = null;
  try {
    const response = await statsService.getWeeklyCustomers(selectedYears.value);
    if (response.data.ok !== false) {
      weeklyData.value = response.data.years || [];
    } else {
      error.value = 'Failed to load data';
    }
  } catch {
    error.value = 'An error occurred while fetching data';
  } finally {
    loading.value = false;
  }
}

watch(selectedYears, fetchData, { deep: true });
onMounted(fetchData);
</script>
