import { useQuery } from "@tanstack/react-query"
import { apiFetch } from '@/utils/api';
import { BarChart, Bar, ResponsiveContainer, XAxis, YAxis, Tooltip as RechartsTooltip, Cell, LineChart, Line } from "recharts"
import config from "@/config"
import { Target, TrendingDown, ArrowUpDown, Swords } from "lucide-react"
import { Tooltip as UITooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"
import { PHASE_CONFIG } from "@/utils/lifecyclePhases"

interface OverallMetrics {
  sampleSize: number
  totalActual: number
  totalForecast: number
  mae: number | null
  wmape: number | null
  bias: number | null
  rmse: number | null
  naiveWmape?: number | null
  fva?: number | null
}

interface PhaseAccuracy {
  phase: string
  sampleSize: number
  totalActual: number
  totalForecast: number
  mae: number | null
  wmape: number | null
  bias: number | null
  rmse: number | null
  naiveWmape?: number | null
  fva?: number | null
}

interface LeadTimeAccuracy {
  bucket: string
  sampleSize: number
  mae: number | null
  wmape: number | null
  bias: number | null
  rmse: number | null
}

interface AccuracyTrendPoint {
  date: string
  mae: number | null
  wmape: number | null
  bias: number | null
  sampleSize: number
}

interface AccuracyData {
  hasData: boolean
  message?: string
  computedAt?: string
  daysOfHistory?: number
  historyRange?: { from: string; to: string }
  overall?: OverallMetrics
  overallInclDormant?: OverallMetrics
  overallWeekly?: OverallMetrics
  byPhase?: PhaseAccuracy[]
  byLeadTime?: LeadTimeAccuracy[]
  byMethod?: { method: string; sampleSize: number; mae: number | null; wmape: number | null; bias: number | null }[]
  dailyTrend?: { date: string; mae: number | null; wmape: number | null; bias: number | null }[]
  accuracyTrend?: AccuracyTrendPoint[]
  accuracyTrendWeekly?: { date: string; wmape: number | null; naiveWmape: number | null; fva: number | null; sampleSize: number }[]
}

function MetricSkeleton() {
  return <div className="h-7 w-16 animate-pulse rounded bg-muted" />;
}

function formatWmape(wmape: number | null): string {
  if (wmape === null) return "N/A"
  return `${wmape.toFixed(1)}%`
}

function formatBias(bias: number | null): string {
  if (bias === null) return "N/A"
  const sign = bias > 0 ? "+" : ""
  return `${sign}${bias.toFixed(3)}`
}

function getAccuracyColor(wmape: number | null): string {
  // Daily-grain thresholds (used for the by-phase / lead-time bars).
  if (wmape === null) return "text-muted-foreground"
  if (wmape <= 30) return "text-green-600"
  if (wmape <= 50) return "text-yellow-600"
  return "text-red-600"
}

function getWeeklyAccuracyColor(wmape: number | null): string {
  // Weekly per-product grain has a much lower achievable floor than daily grain
  // on this intermittent-demand catalog, so the headline uses its own thresholds.
  if (wmape === null) return "text-muted-foreground"
  if (wmape <= 60) return "text-green-600"
  if (wmape <= 90) return "text-yellow-600"
  return "text-red-600"
}

function formatSignedPct(ratio: number | null, digits = 0): string {
  // ratio is a fraction (0.7 => +70%); null-safe.
  if (ratio === null || ratio === undefined) return "N/A"
  const pct = ratio * 100
  const sign = pct > 0 ? "+" : ""
  return `${sign}${pct.toFixed(digits)}%`
}

export function ForecastAccuracy() {
  const { data, error, isLoading } = useQuery<AccuracyData>({
    queryKey: ["forecast-accuracy"],
    queryFn: async () => {
      const response = await apiFetch(`${config.apiUrl}/dashboard/forecast/accuracy`)
      if (!response.ok) {
        throw new Error("Failed to fetch forecast accuracy")
      }
      return response.json()
    },
    refetchInterval: 5 * 60 * 1000,
  })

  if (error) {
    return (
      <div>
        <h3 className="text-lg font-medium mb-3">Forecast Accuracy</h3>
        <p className="text-sm text-destructive">Failed to load accuracy data</p>
      </div>
    )
  }

  if (!isLoading && data && !data.hasData) {
    return (
      <div>
        <h3 className="text-lg font-medium mb-3">Forecast Accuracy</h3>
        <p className="text-sm text-muted-foreground">
          Accuracy data will be available after the forecast engine has run for at least 2 days,
          building up historical comparisons between predictions and actual sales.
        </p>
      </div>
    )
  }

  const phaseChartData = (data?.byPhase || [])
    .filter(p => p.wmape !== null && p.phase !== 'dormant')
    .map(p => ({
      phase: PHASE_CONFIG[p.phase]?.label || p.phase,
      rawPhase: p.phase,
      wmape: p.wmape,
      mae: p.mae,
      bias: p.bias,
      sampleSize: p.sampleSize,
    }))
    .sort((a, b) => (a.wmape ?? 100) - (b.wmape ?? 100))

  const leadTimeData = (data?.byLeadTime || []).map(lt => ({
    bucket: lt.bucket,
    wmape: lt.wmape,
    mae: lt.mae,
    sampleSize: lt.sampleSize,
  }))

  // Headline prefers the weekly-grain WMAPE (informative); falls back to the
  // daily-grain number until enough complete weeks of history exist.
  const weeklyWmape = data?.overallWeekly?.wmape ?? null
  const usingWeekly = weeklyWmape !== null
  const headlineWmape = usingWeekly ? weeklyWmape : (data?.overall?.wmape ?? null)
  const headlineColor = usingWeekly
    ? getWeeklyAccuracyColor(headlineWmape)
    : getAccuracyColor(headlineWmape)
  // Net forecast-vs-actual ratio (e.g. +70% = over-forecasting), from the
  // daily 'all' totals — far more legible than bias in raw units.
  const totalFc = data?.overall?.totalForecast ?? 0
  const totalAct = data?.overall?.totalActual ?? 0
  const fcVsAct = totalAct > 0 ? (totalFc / totalAct - 1) : null
  // Value over the naive baseline; prefer weekly grain to match the headline.
  const naiveSource = data?.overallWeekly ?? data?.overall
  const naiveWmape = naiveSource?.naiveWmape ?? null
  const fva = naiveSource?.fva ?? null

  return (
    <div>
      <h3 className="text-lg font-medium mb-3">Forecast Accuracy</h3>
      {isLoading ? (
        <div className="flex flex-col gap-4">
          <MetricSkeleton />
          <MetricSkeleton />
        </div>
      ) : (
        <>
          {/* Headline metrics */}
          <div className="flex flex-col gap-4">
              <div className="flex items-baseline justify-between">
                <div className="flex items-center gap-2">
                  <Target className="h-4 w-4 text-muted-foreground" />
                  <p className="text-sm font-medium text-muted-foreground">
                    WMAPE <span className="text-[10px] opacity-70">({usingWeekly ? "weekly" : "daily"})</span>
                  </p>
                </div>
                <p className={`text-lg font-bold ${headlineColor}`}>
                  {formatWmape(headlineWmape)}
                </p>
              </div>
              <div className="flex items-baseline justify-between">
                <div className="flex items-center gap-2">
                  <ArrowUpDown className="h-4 w-4 text-muted-foreground" />
                  <p className="text-sm font-medium text-muted-foreground">Forecast vs actual</p>
                </div>
                <p className="text-lg font-bold">
                  {formatSignedPct(fcVsAct)}
                  <span className="text-xs font-normal text-muted-foreground ml-1">
                    {(fcVsAct ?? 0) > 0 ? "over" : (fcVsAct ?? 0) < 0 ? "under" : ""}
                  </span>
                </p>
              </div>
              <div className="flex items-baseline justify-between">
                <div className="flex items-center gap-2">
                  <TrendingDown className="h-4 w-4 text-muted-foreground" />
                  <p className="text-sm font-medium text-muted-foreground">MAE</p>
                </div>
                <p className="text-lg font-bold">
                  {data?.overall?.mae != null ? data?.overall?.mae?.toFixed(2) : "N/A"}
                  <span className="text-xs font-normal text-muted-foreground ml-1">units</span>
                </p>
              </div>
              <div className="flex items-baseline justify-between">
                <div className="flex items-center gap-2">
                  <Swords className="h-4 w-4 text-muted-foreground" />
                  <p className="text-sm font-medium text-muted-foreground">vs naive</p>
                </div>
                <p className="text-lg font-bold">
                  <span className={fva != null ? (fva > 0 ? "text-green-600" : "text-red-600") : "text-muted-foreground"}>
                    {fva != null ? `${formatSignedPct(fva)} FVA` : "N/A"}
                  </span>
                  {naiveWmape != null && (
                    <span className="text-xs font-normal text-muted-foreground ml-1">
                      naive {formatWmape(naiveWmape)}
                    </span>
                  )}
                </p>
              </div>
            </div>

            {/* Phase accuracy bar */}
            {phaseChartData.length > 0 && (
              <div className="mt-4 space-y-1.5">
                <p className="text-xs font-medium text-muted-foreground">WMAPE by Lifecycle Phase</p>
                <TooltipProvider delayDuration={0}>
                  <div className="space-y-1">
                    {phaseChartData.map((p) => {
                      const cfg = PHASE_CONFIG[p.rawPhase] || { label: p.phase, color: "#94A3B8" }
                      const maxWmape = Math.max(...phaseChartData.map(d => d.wmape ?? 0), 1)
                      const barWidth = ((p.wmape ?? 0) / maxWmape) * 100
                      return (
                        <UITooltip key={p.rawPhase}>
                          <TooltipTrigger asChild>
                            <div className="flex items-center gap-2">
                              <span className="text-[10px] text-muted-foreground w-16 text-right shrink-0">{cfg.label}</span>
                              <div className="flex-1 h-3 bg-muted rounded-full overflow-hidden">
                                <div
                                  className="h-full rounded-full transition-all"
                                  style={{
                                    width: `${barWidth}%`,
                                    backgroundColor: cfg.color,
                                    minWidth: barWidth > 0 ? 4 : 0,
                                  }}
                                />
                              </div>
                              <span className="text-[10px] font-medium w-10 text-right shrink-0">
                                {formatWmape(p.wmape)}
                              </span>
                            </div>
                          </TooltipTrigger>
                          <TooltipContent side="bottom" className="text-xs">
                            <div className="font-medium">{cfg.label}</div>
                            <div>WMAPE: {formatWmape(p.wmape)}</div>
                            <div>MAE: {p.mae?.toFixed(3) ?? "N/A"} units</div>
                            <div>Bias: {formatBias(p.bias)}</div>
                            <div className="text-muted-foreground">{p.sampleSize.toLocaleString()} samples</div>
                          </TooltipContent>
                        </UITooltip>
                      )
                    })}
                  </div>
                </TooltipProvider>
              </div>
            )}

            {/* Lead time accuracy chart */}
            {leadTimeData.length > 0 && (
              <div className="mt-4 space-y-1.5">
                <p className="text-xs font-medium text-muted-foreground">Accuracy by Lead Time</p>
                <div className="h-[120px] w-full">
                  <ResponsiveContainer width="100%" height="100%">
                    <BarChart data={leadTimeData} margin={{ top: 5, right: 0, left: -30, bottom: 0 }}>
                      <XAxis
                        dataKey="bucket"
                        tickLine={false}
                        axisLine={false}
                        tick={{ fontSize: 10 }}
                      />
                      <YAxis
                        tickLine={false}
                        axisLine={false}
                        tick={{ fontSize: 10 }}
                        tickFormatter={(v) => `${v}%`}
                      />
                      <RechartsTooltip
                        formatter={(value: number) => [`${value?.toFixed(1)}%`, "WMAPE"]}
                      />
                      <Bar dataKey="wmape" radius={[4, 4, 0, 0]}>
                        {leadTimeData.map((entry, index) => (
                          <Cell
                            key={index}
                            fill={(entry.wmape ?? 0) <= 30 ? "#22C55E" : (entry.wmape ?? 0) <= 50 ? "#F59E0B" : "#EF4444"}
                            fillOpacity={0.7}
                          />
                        ))}
                      </Bar>
                    </BarChart>
                  </ResponsiveContainer>
                </div>
              </div>
            )}

            {/* Accuracy trend sparkline */}
            {data?.accuracyTrend && data.accuracyTrend.length > 1 && (
              <div className="mt-4 space-y-1.5">
                <p className="text-xs font-medium text-muted-foreground">Accuracy Trend (WMAPE)</p>
                <div className="h-[60px] w-full">
                  <ResponsiveContainer width="100%" height="100%">
                    <LineChart data={data.accuracyTrend} margin={{ top: 5, right: 0, left: -60, bottom: 0 }}>
                      <YAxis tickLine={false} axisLine={false} tick={false} />
                      <Line
                        type="monotone"
                        dataKey="wmape"
                        stroke="#8884D8"
                        strokeWidth={2}
                        dot={false}
                      />
                    </LineChart>
                  </ResponsiveContainer>
                </div>
              </div>
            )}

            {/* Footer info */}
            {data?.daysOfHistory !== undefined && (
              <p className="text-[10px] text-muted-foreground mt-3 mb-2">
                Based on {data.daysOfHistory} day{data.daysOfHistory !== 1 ? "s" : ""} of history
                {data.overall?.sampleSize ? ` (${data.overall.sampleSize.toLocaleString()} samples)` : ""}
              </p>
            )}
        </>
      )}
    </div>
  )
}
