import { useEffect, useMemo } from 'react';
import { X } from 'lucide-react';
import {
  AreaChart, Area, BarChart, Bar, XAxis, YAxis, Tooltip,
  ResponsiveContainer, ReferenceLine, Cell,
} from 'recharts';
import { DAILY_TOTAL_METRICS, METRIC_CONFIG, type MetricId } from './types';
import { useDeviceStore } from './useDeviceStore';

interface MetricChartModalProps {
  metricId: string;
  isOpen: boolean;
  onClose: () => void;
}

// Format a Date as YYYY-MM-DD using LOCAL components, not UTC.
// We can't use d.toISOString().slice(0,10) here because for any user east of
// UTC, that returns yesterday's date once it's after local midnight (e.g.
// in Turkey at 18:00 local / 15:00 UTC, toISOString starts with the right
// day, but if you setHours(0,0,0,0) first to "snap to local midnight" then
// toISOString gives the previous calendar date — which silently shifts the
// whole window by one day and makes today's reading fail to line up).
function toLocalISODate(d: Date): string {
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');
  return `${y}-${m}-${day}`;
}

// Build a continuous list of dates [end-(days-1) ... end] in YYYY-MM-DD form,
// so the chart x-axis always spans the full window even when data is sparse.
function buildDateWindow(days: number): string[] {
  const out: string[] = [];
  const today = new Date();
  for (let i = days - 1; i >= 0; i--) {
    const d = new Date(today);
    d.setDate(today.getDate() - i);
    out.push(toLocalISODate(d));
  }
  return out;
}

export function MetricChartModal({ metricId, isOpen, onClose }: MetricChartModalProps) {
  const config = METRIC_CONFIG[metricId as MetricId];
  const { metricHistory, loadMetricHistory, isLoading } = useDeviceStore();

  const isDailyTotal = DAILY_TOTAL_METRICS.includes(metricId as MetricId);

  useEffect(() => {
    if (!isOpen || !metricId) return;
    const end = toLocalISODate(new Date());
    const start = toLocalISODate(new Date(Date.now() - 30 * 86400000));
    loadMetricHistory(metricId, start, end);
  }, [isOpen, metricId, loadMetricHistory]);

  // Merge real readings into a 30-day window so missing days render as gaps
  // (continuous metrics) or empty bars (daily totals) instead of collapsing
  // the x-axis to whatever sparse points exist.
  const chartData = useMemo(() => {
    const window = buildDateWindow(30);
    const byDate = new Map(metricHistory.map(r => [r.date, r.value]));
    return window.map(date => {
      const v = byDate.get(date);
      return {
        date,
        value: v ?? null,
        label: new Date(date + 'T00:00:00').toLocaleDateString('en-US', {
          month: 'short', day: 'numeric',
        }),
      };
    });
  }, [metricHistory]);

  const realDataPoints = chartData.filter(d => d.value != null);

  const stats = useMemo(() => {
    if (!realDataPoints.length) return null;
    const values = realDataPoints.map(d => d.value as number);
    const avg = values.reduce((s, v) => s + v, 0) / values.length;
    const min = Math.min(...values);
    const max = Math.max(...values);

    // Weekly trend: avg of last 7 vs prior 7
    let trend: number | null = null;
    if (values.length >= 14) {
      const recent = values.slice(-7);
      const prior = values.slice(-14, -7);
      const recentAvg = recent.reduce((s, v) => s + v, 0) / recent.length;
      const priorAvg = prior.reduce((s, v) => s + v, 0) / prior.length;
      if (priorAvg !== 0) trend = ((recentAvg - priorAvg) / priorAvg) * 100;
    }
    return { avg, min, max, trend };
  }, [realDataPoints]);

  if (!isOpen || !config) return null;

  // Sleep gets a special palette/format; other daily totals share blue.
  const isSleep = metricId === 'sleep_duration';
  const barColor = isSleep ? '#6366f1' : '#3b82f6';

  return (
    <>
      <div className="fixed inset-0 bg-slate-900/40 z-40 backdrop-blur-sm" onClick={onClose} />
      <div className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-50 w-[94%] max-w-2xl bg-white rounded-2xl shadow-xl p-6">
        <div className="flex items-center justify-between mb-5">
          <h2 className="text-lg font-semibold text-gray-900">
            {config.label} — Last 30 Days
          </h2>
          <button onClick={onClose} className="p-1.5 rounded-lg hover:bg-gray-100 text-gray-400">
            <X className="w-5 h-5" />
          </button>
        </div>

        {isLoading ? (
          <div className="h-[300px] flex items-center justify-center text-gray-400">Loading...</div>
        ) : realDataPoints.length === 0 ? (
          <div className="h-[300px] flex flex-col items-center justify-center text-gray-400 text-sm">
            <p>No data available for the last 30 days.</p>
            <p className="text-xs mt-1 text-gray-300">
              Open the companion app and tap Sync to upload your latest readings.
            </p>
          </div>
        ) : isDailyTotal ? (
          <ResponsiveContainer width="100%" height={300}>
            <BarChart data={chartData} margin={{ top: 10, right: 10, left: 0, bottom: 0 }}>
              <defs>
                <linearGradient id="barGradient" x1="0" y1="0" x2="0" y2="1">
                  <stop offset="0%" stopColor={barColor} stopOpacity={0.95} />
                  <stop offset="100%" stopColor={barColor} stopOpacity={0.55} />
                </linearGradient>
              </defs>
              <XAxis
                dataKey="label"
                tick={{ fontSize: 11, fill: '#9ca3af' }}
                tickLine={false}
                axisLine={false}
                interval={Math.max(0, Math.floor(chartData.length / 10) - 1)}
              />
              <YAxis
                tick={{ fontSize: 11, fill: '#9ca3af' }}
                tickLine={false}
                axisLine={false}
                width={45}
              />
              <Tooltip
                cursor={{ fill: 'rgba(99, 102, 241, 0.06)' }}
                contentStyle={{ borderRadius: 12, border: '1px solid #e5e7eb', boxShadow: '0 4px 12px rgba(0,0,0,0.08)' }}
                formatter={(v) => {
                  if (v == null || v === '') return ['No data', config.label];
                  const numeric = typeof v === 'number' ? v : Number(v);
                  if (!Number.isFinite(numeric)) return ['No data', config.label];
                  return [config.format(numeric) + ' ' + config.unit, config.label];
                }}
                labelFormatter={(label: string) => label}
              />
              {config.normalRange && (
                <>
                  <ReferenceLine y={config.normalRange.min} stroke="#e5e7eb" strokeDasharray="4 4" />
                  <ReferenceLine y={config.normalRange.max} stroke="#e5e7eb" strokeDasharray="4 4" />
                </>
              )}
              <Bar
                dataKey="value"
                fill="url(#barGradient)"
                radius={[6, 6, 0, 0]}
                maxBarSize={28}
              >
                {chartData.map((d, i) => (
                  <Cell
                    key={i}
                    fill={d.value == null ? '#f3f4f6' : 'url(#barGradient)'}
                  />
                ))}
              </Bar>
            </BarChart>
          </ResponsiveContainer>
        ) : (
          <ResponsiveContainer width="100%" height={300}>
            <AreaChart data={chartData} margin={{ top: 10, right: 10, left: 0, bottom: 0 }}>
              <defs>
                <linearGradient id="metricGradient" x1="0" y1="0" x2="0" y2="1">
                  <stop offset="5%" stopColor="#3b82f6" stopOpacity={0.2} />
                  <stop offset="95%" stopColor="#3b82f6" stopOpacity={0} />
                </linearGradient>
              </defs>
              <XAxis
                dataKey="label"
                tick={{ fontSize: 11, fill: '#9ca3af' }}
                tickLine={false}
                axisLine={false}
                interval={Math.max(0, Math.floor(chartData.length / 10) - 1)}
              />
              <YAxis
                tick={{ fontSize: 11, fill: '#9ca3af' }}
                tickLine={false}
                axisLine={false}
                width={45}
                domain={['auto', 'auto']}
              />
              <Tooltip
                contentStyle={{ borderRadius: 12, border: '1px solid #e5e7eb', boxShadow: '0 4px 12px rgba(0,0,0,0.08)' }}
                formatter={(v) => {
                  if (v == null || v === '') return ['No data', config.label];
                  const numeric = typeof v === 'number' ? v : Number(v);
                  if (!Number.isFinite(numeric)) return ['No data', config.label];
                  return [config.format(numeric) + ' ' + config.unit, config.label];
                }}
                labelFormatter={(label: string) => label}
              />
              {config.normalRange && (
                <>
                  <ReferenceLine y={config.normalRange.min} stroke="#d1d5db" strokeDasharray="4 4" />
                  <ReferenceLine y={config.normalRange.max} stroke="#d1d5db" strokeDasharray="4 4" />
                </>
              )}
              <Area
                type="monotone"
                dataKey="value"
                stroke="#3b82f6"
                strokeWidth={2}
                fill="url(#metricGradient)"
                connectNulls
                dot={false}
                activeDot={{ r: 4, fill: '#3b82f6' }}
              />
            </AreaChart>
          </ResponsiveContainer>
        )}

        {/* Stats row */}
        {stats && (
          <div className="grid grid-cols-4 gap-4 mt-5 pt-4 border-t border-gray-100">
            <Stat label="Average" value={config.format(stats.avg)} unit={config.unit} />
            <Stat label="Min" value={config.format(stats.min)} unit={config.unit} />
            <Stat label="Max" value={config.format(stats.max)} unit={config.unit} />
            <Stat
              label="Weekly Trend"
              value={stats.trend != null ? `${stats.trend > 0 ? '+' : ''}${stats.trend.toFixed(1)}%` : '—'}
              unit=""
            />
          </div>
        )}
      </div>
    </>
  );
}

function Stat({ label, value, unit }: { label: string; value: string; unit: string }) {
  return (
    <div className="text-center">
      <p className="text-[11px] text-gray-400 mb-0.5">{label}</p>
      <p className="text-sm font-semibold text-gray-800">{value} <span className="text-[10px] font-normal text-gray-400">{unit}</span></p>
    </div>
  );
}
