// src/features/admin-analytics/Analytics.tsx
// Admin analytics page — rolling/calendar time-bucket KPIs and leaderboards.

'use client';

import { useState, useEffect, useCallback } from 'react';
import { useT, useLocale } from '@/lib/i18n/react';
import { MetricTile } from '@/components/ui/domain/MetricTile';
import { AdminPanel } from '@/components/ui/domain/admin/AdminPanel';
import { AdminTable, type ColumnDef } from '@/components/ui/domain/admin/AdminTable';
import { AdminTimeSeriesChart } from '@/components/ui/domain/admin/AdminTimeSeriesChart';
import { Stack } from '@/components/ui/layout/Stack';
import { PageHeader } from '@/components/ui/layout/PageHeader';
import { Button } from '@/components/ui/primitives/Button';
import { InlineNotice } from '@/components/ui/feedback/InlineNotice';
import { Icon } from '@/components/ui/icons/Icon';
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from '@/components/ui/overlays/Tooltip';
import type {
  AnalyticsResult,
  BucketMode,
  BucketSize,
  VendorLeaderboardRow,
  CustomerLeaderboardRow,
  DealLeaderboardRow,
} from '@/server/admin/resources/analytics/queries';
import type { AnalyticsTimeSeriesResult } from '@/server/admin/resources/analytics/time-series';
import type {
  DashboardMetrics,
  DashboardMetricDeltas,
} from '@/server/admin/resources/dashboard/queries';
import { ErrorBoundary } from '@/components/ui/feedback/ErrorBoundary';
import { ErrorState } from '@/components/ui/feedback/ErrorState';
import { formatInteger } from '@/lib/format';
import { formatAgorotLocale } from '@/lib/money';
import type { Locale } from '@/lib/i18n/index';

// ─── Props ────────────────────────────────────────────────────────────────────

export interface AnalyticsProps {
  initialData: AnalyticsResult;
  initialMode: BucketMode;
  initialBucket: BucketSize;
  dashboardMetrics: DashboardMetrics;
  dashboardDeltas?: DashboardMetricDeltas;
  dataLoadFailed?: boolean;
}

// ─── Formatting helpers ───────────────────────────────────────────────────────

function formatShekelAmount(value: string | number, locale: Locale): string {
  const num = parseFloat(String(value));
  return formatAgorotLocale(Number.isFinite(num) ? Math.round(num * 100) : 0, locale);
}

function formatUsd(value: string | number): string {
  const num = parseFloat(String(value));
  if (isNaN(num)) return '$0.00';
  return '$' + num.toFixed(2);
}

// ─── Delta helper ─────────────────────────────────────────────────────────────

function toDelta(
  pct: number | null | undefined,
  noChangeLabel: string,
): { value: number; dir: 'up' | 'warn' | 'down' | 'neutral'; label?: string } | undefined {
  if (pct == null) return undefined;
  if (pct > 0) return { value: Math.abs(pct), dir: 'up' };
  if (pct < 0) return { value: Math.abs(pct), dir: 'down' };
  return { value: 0, dir: 'neutral', label: noChangeLabel };
}

// ─── URL param helpers ────────────────────────────────────────────────────────

function updateUrlParams(mode: BucketMode, bucket: BucketSize): void {
  if (typeof window === 'undefined') return;
  const sp = new URLSearchParams(window.location.search);
  sp.set('mode', mode);
  sp.set('bucket', bucket);
  window.history.replaceState(null, '', `${window.location.pathname}?${sp.toString()}`);
}

// ─── Component ────────────────────────────────────────────────────────────────

export function Analytics({
  initialData,
  initialMode,
  initialBucket,
  dashboardMetrics,
  dashboardDeltas,
  dataLoadFailed = false,
}: AnalyticsProps) {
  const t = useT('admin_analytics');
  const tCommon = useT('common');
  const tMetric = useT('admin_metric_tile');
  const noChangeLabel = tMetric('no_change');
  const { locale } = useLocale();

  const [mode, setMode] = useState<BucketMode>(initialMode);
  const [bucket, setBucket] = useState<BucketSize>(initialBucket);
  const [data, setData] = useState<AnalyticsResult>(initialData);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [timeSeries, setTimeSeries] = useState<AnalyticsTimeSeriesResult | null>(null);
  const [, setIsChartsLoading] = useState(true);

  // Whether this is the initial render (skip KPI refetch — use SSR data)
  const isInitialRender = mode === initialMode && bucket === initialBucket;

  const fetchAnalytics = useCallback(
    async (m: BucketMode, b: BucketSize, signal?: AbortSignal) => {
      setIsLoading(true);
      setError(null);
      try {
        const url = `/api/admin/analytics?mode=${m}&bucket=${b}`;
        const res = await fetch(url, { signal });
        if (!res.ok) throw new Error(`HTTP ${res.status}`);
        const json = (await res.json()) as { ok: boolean; analytics: AnalyticsResult };
        setData(json.analytics);
      } catch (err) {
        if ((err as Error).name !== 'AbortError') {
          setError(t('fetch_error'));
        }
      } finally {
        setIsLoading(false);
      }
    },
    [t],
  );

  const fetchTimeSeries = useCallback(
    async (m: BucketMode, b: BucketSize, signal?: AbortSignal) => {
      setIsChartsLoading(true);
      try {
        const url = `/api/admin/analytics/timeseries?mode=${m}&bucket=${b}`;
        const res = await fetch(url, { signal });
        if (!res.ok) throw new Error(`HTTP ${res.status}`);
        const json = (await res.json()) as { ok: boolean; timeSeries: AnalyticsTimeSeriesResult };
        setTimeSeries(json.timeSeries);
      } catch (err) {
        if ((err as Error).name !== 'AbortError') {
          setError(t('fetch_error'));
        }
      } finally {
        setIsChartsLoading(false);
      }
    },
    [t],
  );

  // Refetch when mode/bucket changes (skip KPI fetch on first render — use SSR data)
  useEffect(() => {
    if (isInitialRender) return;
    const controller = new AbortController();

    void Promise.resolve().then(() => fetchAnalytics(mode, bucket, controller.signal));
    return () => controller.abort();
  }, [fetchAnalytics, isInitialRender, mode, bucket]);

  // Always fetch time series (no SSR equivalent)
  useEffect(() => {
    const controller = new AbortController();

    void Promise.resolve().then(() => fetchTimeSeries(mode, bucket, controller.signal));
    return () => controller.abort();
  }, [fetchTimeSeries, mode, bucket]);

  function handleModeChange(next: BucketMode) {
    setMode(next);
    updateUrlParams(next, bucket);
  }

  function handleBucketChange(next: BucketSize) {
    setBucket(next);
    updateUrlParams(mode, next);
  }

  const buckets: { value: BucketSize; label: string }[] = [
    { value: 'd', label: t('bucket_d') },
    { value: 'w', label: t('bucket_w') },
    { value: 'm', label: t('bucket_m') },
    { value: 'y', label: t('bucket_y') },
    { value: 'all', label: t('bucket_all') },
  ];

  const modes: { value: BucketMode; label: string }[] = [
    { value: 'rolling', label: t('mode_rolling') },
    { value: 'calendar', label: t('mode_calendar') },
  ];

  // ── Leaderboard column definitions ───────────────────────────────────────

  const vendorCols: ColumnDef<VendorLeaderboardRow & { id: string }>[] = [
    {
      key: 'businessName',
      label: t('leaderboard_vendor_name'),
      render: (r) => r.businessName,
    },
    {
      key: 'revenue',
      label: t('leaderboard_vendor_revenue'),
      align: 'end',
      render: (r) => formatShekelAmount(r.revenue, locale),
    },
  ];

  const customerCols: ColumnDef<CustomerLeaderboardRow & { id: string }>[] = [
    {
      key: 'displayName',
      label: t('leaderboard_customer_name'),
      render: (r) => r.displayName || t('leaderboard_customer_guest'),
    },
    {
      key: 'totalSpend',
      label: t('leaderboard_customer_spend'),
      align: 'end',
      render: (r) => formatShekelAmount(r.totalSpend, locale),
    },
  ];

  const dealCols: ColumnDef<DealLeaderboardRow & { id: string }>[] = [
    {
      key: 'title',
      label: t('leaderboard_deal_title'),
      render: (r) => r.title,
    },
    {
      key: 'purchaseCount',
      label: t('leaderboard_deal_purchases'),
      align: 'end',
      render: (r) => formatInteger(r.purchaseCount, locale),
    },
  ];

  const topVendorsWithId = data.topVendors.map((r) => ({ ...r, id: r.vendorId }));
  const topCustomersWithId = data.topCustomers.map((r) => ({ ...r, id: r.userId }));
  const topDealsWithId = data.topDeals.map((r) => ({ ...r, id: r.dealId }));

  const llmCostNum = parseFloat(data.llmCostUsd);
  const showLlmComingSoon = (isNaN(llmCostNum) || llmCostNum === 0) && bucket === 'all';
  return (
    <ErrorBoundary>
      <div>
        <Stack gap="8">
          <PageHeader title={t('page_title')} />

          {error && <InlineNotice tone="danger" title={error} />}

          {/* ── Overview tiles ──────────────────────────────────────────────── */}
          <AdminPanel>
            <section aria-labelledby="overview-heading">
              <h2
                id="overview-heading"
                className="text-text-secondary mb-3 text-sm font-semibold tracking-wide uppercase"
              >
                {t('section_overview')}
              </h2>
              {dataLoadFailed ? (
                <ErrorState
                  title={tCommon('error_loading')}
                  action={
                    <Button variant="secondary" size="sm" onClick={() => window.location.reload()}>
                      {tCommon('retry')}
                    </Button>
                  }
                />
              ) : (
                <div className="grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-6">
                  <MetricTile
                    value={formatInteger(dashboardMetrics.activeVendors, locale)}
                    label={t('metric_active_vendors')}
                    tone="default"
                    delta={toDelta(dashboardDeltas?.activeVendors, noChangeLabel)}
                  />
                  <MetricTile
                    value={formatInteger(dashboardMetrics.activeDeals, locale)}
                    label={t('metric_active_deals')}
                    tone="default"
                    delta={toDelta(dashboardDeltas?.activeDeals, noChangeLabel)}
                  />
                  <MetricTile
                    value={formatInteger(data.totalCustomers, locale)}
                    label={t('metric_total_customers')}
                    tone="default"
                    delta={toDelta(dashboardDeltas?.totalUsers, noChangeLabel)}
                  />
                  <MetricTile
                    value={formatInteger(data.itemsPendingModeration, locale)}
                    label={t('metric_pending_moderation')}
                    tone={data.itemsPendingModeration > 0 ? 'warning' : 'default'}
                    delta={toDelta(dashboardDeltas?.pendingDeals, noChangeLabel)}
                  />
                  <MetricTile
                    value={formatShekelAmount(dashboardMetrics.totalCommission, locale)}
                    label={t('metric_commission')}
                    tone="success"
                    delta={toDelta(dashboardDeltas?.totalCommission, noChangeLabel)}
                  />
                  <MetricTile
                    value={formatShekelAmount(dashboardMetrics.totalGmv, locale)}
                    label={t('metric_gmv')}
                    tone="success"
                    delta={toDelta(dashboardDeltas?.totalGmv, noChangeLabel)}
                  />
                </div>
              )}
            </section>
          </AdminPanel>

          {/* ── Mode + bucket toggles ───────────────────────────────────────── */}
          <div className="flex flex-wrap items-center justify-center gap-4">
            {/* Mode toggle + tooltip */}
            <div className="flex items-center gap-1.5">
              <div
                role="group"
                aria-label={t('mode_group_label')}
                className="bg-surface-base border-border-default inline-flex gap-0.5 rounded-md border p-0.5"
              >
                {modes.map(({ value, label }) => (
                  <Button
                    key={value}
                    variant={mode === value ? 'primary' : 'ghost'}
                    size="sm"
                    aria-pressed={mode === value}
                    onClick={() => handleModeChange(value)}
                  >
                    {label}
                  </Button>
                ))}
              </div>
              <TooltipProvider>
                <Tooltip>
                  <TooltipTrigger asChild>
                    <Button
                      variant="ghost"
                      size="sm"
                      className="text-text-secondary hover:text-text-primary flex items-center p-1"
                      aria-label={t('mode_group_label')}
                    >
                      <Icon name="Info" size="sm" color="muted" />
                    </Button>
                  </TooltipTrigger>
                  <TooltipContent side="bottom" className="max-w-64 text-center whitespace-normal">
                    {t('mode_tooltip')}
                  </TooltipContent>
                </Tooltip>
              </TooltipProvider>
            </div>

            {/* Bucket toggle */}
            <div
              role="group"
              aria-label={t('bucket_group_label')}
              className="bg-surface-base border-border-default inline-flex gap-0.5 rounded-md border p-0.5"
            >
              {buckets.map(({ value, label }) => (
                <Button
                  key={value}
                  variant={bucket === value ? 'primary' : 'ghost'}
                  size="sm"
                  aria-pressed={bucket === value}
                  onClick={() => handleBucketChange(value)}
                >
                  {label}
                </Button>
              ))}
            </div>
          </div>

          {/* ── Data area (keep mounted during refetch) ─────────────────────── */}
          <div className="relative">
            {isLoading && (
              <div className="absolute end-0 top-0 z-10">
                <span className="bg-surface-base/90 text-text-muted rounded-full px-3 py-1 text-xs shadow-sm">
                  {tCommon('loading')}
                </span>
              </div>
            )}

            {/* ── Error state ─────────────────────────────────────────────────── */}
            {error && (
              <p role="alert" className="bg-danger-50 text-danger-700 rounded-md p-3 text-sm">
                {error}
              </p>
            )}

            {/* ── KPI tiles — bucketed ─────────────────────────────────────────── */}
            <AdminPanel>
              <section aria-labelledby="kpi-bucketed-heading">
                <h2
                  id="kpi-bucketed-heading"
                  className="text-text-secondary mb-3 text-sm font-semibold tracking-wide uppercase"
                >
                  {t('section_period')}
                </h2>
                <div className="grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-6">
                  <MetricTile
                    value={formatShekelAmount(data.revenue, locale)}
                    label={t('metric_revenue')}
                    tone="success"
                    delta={toDelta(dashboardDeltas?.totalGmv, noChangeLabel)}
                  />
                  <MetricTile
                    value={formatInteger(data.dealsCreated, locale)}
                    label={t('metric_deals')}
                    tone="default"
                    delta={toDelta(dashboardDeltas?.activeDeals, noChangeLabel)}
                  />
                  <MetricTile
                    value={formatInteger(data.purchasesCompleted, locale)}
                    label={t('metric_purchases')}
                    tone="default"
                    delta={toDelta(dashboardDeltas?.totalPurchases, noChangeLabel)}
                  />
                  <MetricTile
                    value={formatInteger(data.newCustomers, locale)}
                    label={t('metric_new_customers')}
                    tone="default"
                    delta={toDelta(dashboardDeltas?.newUsers, noChangeLabel)}
                  />
                  <MetricTile
                    value={formatInteger(data.newVendors, locale)}
                    label={t('metric_new_vendors')}
                    tone="default"
                    delta={toDelta(dashboardDeltas?.activeVendors, noChangeLabel)}
                  />
                  <div>
                    <MetricTile
                      value={formatUsd(data.llmCostUsd)}
                      label={t('metric_llm_costs')}
                      tone="default"
                    />
                    {showLlmComingSoon && (
                      <p className="text-text-secondary mt-1 text-xs">{t('llm_coming_soon')}</p>
                    )}
                  </div>
                </div>
              </section>
            </AdminPanel>

            {/* ── Charts ───────────────────────────────────────────────────────── */}
            <AdminPanel>
              <section aria-labelledby="charts-heading">
                <h2
                  id="charts-heading"
                  className="text-text-secondary mb-4 text-sm font-semibold tracking-wide uppercase"
                >
                  {t('section_charts')}
                </h2>
                <div className="grid grid-cols-6 gap-4">
                  <div className="col-span-6">
                    <AdminTimeSeriesChart
                      data={timeSeries?.revenue ?? []}
                      title={t('chart_revenue')}
                      format="currency"
                      bucketSize={bucket}
                    />
                  </div>
                  <div className="col-span-6 sm:col-span-3">
                    <AdminTimeSeriesChart
                      data={timeSeries?.activeDeals ?? []}
                      title={t('chart_active_deals')}
                      format="count"
                      bucketSize={bucket}
                    />
                  </div>
                  <div className="col-span-6 sm:col-span-3">
                    <AdminTimeSeriesChart
                      data={timeSeries?.purchasesCompleted ?? []}
                      title={t('chart_purchases')}
                      format="count"
                      bucketSize={bucket}
                    />
                  </div>
                  <div className="col-span-6 sm:col-span-3">
                    <AdminTimeSeriesChart
                      data={timeSeries?.totalCustomers ?? []}
                      title={t('chart_total_customers')}
                      format="count"
                      bucketSize={bucket}
                    />
                  </div>
                  <div className="col-span-6 sm:col-span-3">
                    <AdminTimeSeriesChart
                      data={timeSeries?.totalVendors ?? []}
                      title={t('chart_total_vendors')}
                      format="count"
                      bucketSize={bucket}
                    />
                  </div>
                  <div className="col-span-6 sm:col-span-2">
                    <AdminTimeSeriesChart
                      data={timeSeries?.newCustomers ?? []}
                      title={t('chart_new_customers')}
                      format="count"
                      bucketSize={bucket}
                    />
                  </div>
                  <div className="col-span-6 sm:col-span-2">
                    <AdminTimeSeriesChart
                      data={timeSeries?.newVendors ?? []}
                      title={t('chart_new_vendors')}
                      format="count"
                      bucketSize={bucket}
                    />
                  </div>
                  <div className="col-span-6 sm:col-span-2">
                    <AdminTimeSeriesChart
                      data={timeSeries?.llmCostUsd ?? []}
                      title={t('chart_llm_costs')}
                      format="usd"
                      bucketSize={bucket}
                    />
                  </div>
                </div>
              </section>
            </AdminPanel>

            {/* ── Leaderboards ─────────────────────────────────────────────────── */}
            <AdminPanel>
              <section aria-labelledby="leaderboards-heading">
                <h2
                  id="leaderboards-heading"
                  className="text-text-secondary mb-4 text-sm font-semibold tracking-wide uppercase"
                >
                  {t('section_leaderboards')}
                </h2>
                <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
                  <div>
                    <h3 className="text-text-primary mb-2 text-sm font-semibold">
                      {t('leaderboard_top_vendors')}
                    </h3>
                    <AdminTable
                      columns={vendorCols}
                      rows={topVendorsWithId}
                      rowHref={(r) => `/admin/vendors/${r.vendorId}`}
                    />
                  </div>

                  <div>
                    <h3 className="text-text-primary mb-2 text-sm font-semibold">
                      {t('leaderboard_top_customers')}
                    </h3>
                    <AdminTable
                      columns={customerCols}
                      rows={topCustomersWithId}
                      rowHref={(r) => `/admin/users/${r.userId}`}
                    />
                  </div>

                  <div>
                    <h3 className="text-text-primary mb-2 text-sm font-semibold">
                      {t('leaderboard_top_deals')}
                    </h3>
                    <AdminTable
                      columns={dealCols}
                      rows={topDealsWithId}
                      rowHref={(r) => `/admin/deals/${r.dealId}`}
                    />
                  </div>
                </div>
              </section>
            </AdminPanel>
          </div>
        </Stack>
      </div>
    </ErrorBoundary>
  );
}
