"use client";
import React, { useEffect, useMemo, useState } from "react";
import { motion } from "framer-motion";
import {
  Card,
  CardContent,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Progress } from "@/components/ui/progress";
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
import { Switch } from "@/components/ui/switch";
import { CalendarDays, CheckCircle2, Flame, RefreshCcw, Target, TrendingUp } from "lucide-react";
import {
  LineChart,
  Line,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip as RTooltip,
  ResponsiveContainer,
  Legend,
} from "recharts";

interface DayPlan {
  date: string;
  planned: number;
  actual: number;
}

interface PlanState {
  totalPages: number;
  startDate: string;
  endDate: string;
  includeWeekends: boolean;
  days: DayPlan[];
}

function toYMD(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}`;
}

function fromYMD(s: string): Date {
  const [y, m, d] = s.split("-").map(Number);
  return new Date(y, (m || 1) - 1, d || 1);
}

function isWeekend(d: Date): boolean {
  const day = d.getDay();
  return day === 0 || day === 6;
}

function eachDay(start: Date, end: Date, includeWeekends = true): string[] {
  const out: string[] = [];
  const cur = new Date(start);
  cur.setHours(0, 0, 0, 0);
  const last = new Date(end);
  last.setHours(0, 0, 0, 0);
  while (cur <= last) {
    if (includeWeekends || !isWeekend(cur)) {
      out.push(toYMD(cur));
    }
    cur.setDate(cur.getDate() + 1);
  }
  return out;
}

function distribute(total: number, buckets: number): number[] {
  if (buckets <= 0) return [];
  const base = Math.floor(total / buckets);
  const remainder = total - base * buckets;
  const arr = Array.from({ length: buckets }, (_, i) => base + (i < remainder ? 1 : 0));
  return arr;
}

function formatPretty(s: string): string {
  try {
    const d = fromYMD(s);
    return d.toLocaleDateString(undefined, { weekday: "short", month: "short", day: "numeric" });
  } catch {
    return s;
  }
}

const LS_KEY = "study-tracker-plan-v1";

function savePlan(p: PlanState) {
  if (typeof window === "undefined") return;
  localStorage.setItem(LS_KEY, JSON.stringify(p));
}

function loadPlan(): PlanState | null {
  if (typeof window === "undefined") return null;
  const raw = localStorage.getItem(LS_KEY);
  if (!raw) return null;
  try {
    const parsed = JSON.parse(raw) as PlanState;
    return parsed;
  } catch {
    return null;
  }
}

export default function StudyTrackerApp() {
  const todayYMD = toYMD(new Date());
  const [totalPages, setTotalPages] = useState<number>(200);
  const [endDate, setEndDate] = useState<string>(toYMD(new Date(Date.now() + 7 * 86400000)));
  const [includeWeekends, setIncludeWeekends] = useState<boolean>(true);
  const [days, setDays] = useState<DayPlan[]>([]);

  useEffect(() => {
    const stored = loadPlan();
    if (stored) {
      setTotalPages(stored.totalPages);
      setEndDate(stored.endDate);
      setIncludeWeekends(stored.includeWeekends);
      setDays(stored.days);
    } else {
      buildPlan();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  function buildPlan() {
    const start = new Date();
    start.setHours(0, 0, 0, 0);
    const end = fromYMD(endDate);
    end.setHours(0, 0, 0, 0);

    if (isNaN(totalPages) || totalPages <= 0 || end < start) {
      setDays([]);
      return;
    }

    const slots = eachDay(start, end, includeWeekends);
    const allocation = distribute(totalPages, slots.length);

    const newDays: DayPlan[] = slots.map((ymd, i) => {
      const existing = days.find((d) => d.date === ymd);
      return {
        date: ymd,
        planned: allocation[i] || 0,
        actual: existing?.actual || 0,
      };
    });

    setDays(newDays);

    const state: PlanState = {
      totalPages,
      startDate: todayYMD,
      endDate,
      includeWeekends,
      days: newDays,
    };
    savePlan(state);
  }

  useEffect(() => {
    const state: PlanState = {
      totalPages,
      startDate: todayYMD,
      endDate,
      includeWeekends,
      days,
    };
    savePlan(state);
  }, [days, totalPages, endDate, includeWeekends, todayYMD]);

  const stats = useMemo(() => {
    const studied = days.reduce((sum, d) => sum + (d.actual || 0), 0);
    const planned = days.reduce((sum, d) => sum + (d.planned || 0), 0);
    const pct = planned > 0 ? Math.min(100, Math.round((studied / planned) * 100)) : 0;
    const remaining = Math.max(0, planned - studied);
    const avgPerDay = days.length ? Math.round(planned / days.length) : 0;
    return { studied, planned, pct, remaining, avgPerDay };
  }, [days]);

  const chartData = useMemo(() => {
    let cumPlanned = 0;
    let cumActual = 0;
    return days.map((d) => {
      cumPlanned += d.planned;
      cumActual += d.actual || 0;
      return {
        date: formatPretty(d.date),
        Planned: cumPlanned,
        Actual: cumActual,
      };
    });
  }, [days]);

  function updateActual(ymd: string, value: number) {
    setDays((prev) => prev.map((d) => (d.date === ymd ? { ...d, actual: Math.max(0, Math.floor(value || 0)) } : d)));
  }

  function bumpActual(ymd: string, inc: number) {
    setDays((prev) => prev.map((d) => (d.date === ymd ? { ...d, actual: Math.max(0, (d.actual || 0) + inc) } : d)));
  }

  function resetProgress() {
    setDays((prev) => prev.map((d) => ({ ...d, actual: 0 })));
  }

  function resetAll() {
    setTotalPages(200);
    setEndDate(toYMD(new Date(Date.now() + 7 * 86400000)));
    setIncludeWeekends(true);
    setDays([]);
    if (typeof window !== "undefined") localStorage.removeItem(LS_KEY);
    buildPlan();
  }

  const deadlinePassed = new Date(endDate).setHours(0, 0, 0, 0) < new Date().setHours(0, 0, 0, 0);

  return (
    <div className="min-h-screen w-full bg-gradient-to-b from-slate-50 to-white p-4 md:p-8">
      <div className="mx-auto max-w-6xl space-y-6">
        <header className="flex flex-col gap-3 md:flex-row md:items-end md:justify-between">
          <div>
            <h1 className="text-3xl font-bold tracking-tight">Study Tracker</h1>
            <p className="text-slate-600">Split your pages, track your progress, and finish on time.</p>
          </div>
          <div className="flex items-center gap-2">
            <Button variant="secondary" onClick={resetProgress} className="gap-2">
              <RefreshCcw className="h-4 w-4" /> Reset progress
            </Button>
            <Button variant="ghost" onClick={resetAll} className="gap-2">
              <RefreshCcw className="h-4 w-4" /> Reset all
            </Button>
          </div>
        </header>

        <Card className="shadow-sm">
          <CardHeader>
            <CardTitle className="flex items-center gap-2">
              <Target className="h-5 w-5" /> Plan your study
            </CardTitle>
          </CardHeader>
          <CardContent className="grid gap-4 md:grid-cols-4">
            <div className="space-y-2">
              <Label htmlFor="totalPages">Total pages</Label>
              <Input
                id="totalPages"
                type="number"
                min={1}
                value={totalPages}
                onChange={(e) => setTotalPages(Math.max(0, Math.floor(Number(e.target.value) || 0)))}
              />
            </div>
            <div className="space-y-2">
              <Label htmlFor="endDate" className="flex items-center gap-2">
                <CalendarDays className="h-4 w-4" /> Deadline
              </Label>
              <Input id="endDate" type="date" value={endDate} onChange={(e) => setEndDate(e.target.value)} />
            </div>
            <div className="flex items-center justify-between rounded-2xl border p-4">
              <div>
                <div className="font-medium">Include weekends</div>
                <div className="text-sm text-slate-500">Count Saturdays & Sundays in the plan</div>
              </div>
              <Switch checked={includeWeekends} onCheckedChange={setIncludeWeekends} />
            </div>
            <div className="flex items-end">
              <Button className="w-full" onClick={buildPlan}>
                Build / Update plan
              </Button>
            </div>
            {deadlinePassed && (
              <div className="md:col-span-4 text-sm text-red-600">The deadline date is in the past. Please choose a future date.</div>
            )}
          </CardContent>
        </Card>

        <div className="grid gap-4 md:grid-cols-3">
          <Card>
            <CardHeader>
              <CardTitle className="flex items-center gap-2 text-base">
                <TrendingUp className="h-4 w-4" /> Overall progress
              </CardTitle>
            </CardHeader>
            <CardContent className="space-y-3">
              <div className="flex justify-between text-sm text-slate-600">
                <span>
                  {stats.studied} / {stats.planned} pages
                </span>
                <span>{stats.pct}%</span>
              </div>
              <Progress value={stats.pct} />
              <div className="text-xs text-slate-500">{stats.remaining} pages remaining</div>
            </CardContent>
          </Card>
          <Card>
            <CardHeader>
              <CardTitle className="flex items-center gap-2 text-base">
                <Flame className="h-4 w-4" /> Pace
              </CardTitle>
            </CardHeader>
            <CardContent className="space-y-1 text-sm">
              <div>
                Average planned per day: <span className="font-semibold">{stats.avgPerDay}</span>
              </div>
              <div>
                Days in plan: <span className="font-semibold">{days.length}</span>
              </div>
              <div>
                Finish by: <span className="font-semibold">{formatPretty(endDate)}</span>
              </div>
            </CardContent>
          </Card>
          <Card>
            <CardHeader>
              <CardTitle className="flex items-center gap-2 text-base">
                <CheckCircle2 className="h-4 w-4" /> Streaks
              </CardTitle>
            </CardHeader>
            <CardContent>
              <StreakBadge days={days} />
            </CardContent>
          </Card>
        </div>

        <Tabs defaultValue="calendar" className="w-full">
          <TabsList>
            <TabsTrigger value="calendar">Daily</TabsTrigger>
            <TabsTrigger value="chart">Progress chart</TabsTrigger>
          </TabsList>
          <TabsContent value="chart">
            <Card>
              <CardHeader>
                <CardTitle>Planned vs. Actual (cumulative)</CardTitle>
              </CardHeader>
              <CardContent className="h-72">
                {chartData.length > 0 ? (
                  <ResponsiveContainer width="100%" height="100%">
                    <LineChart data={chartData} margin={{ top: 8, right: 16, bottom: 8, left: 0 }}>
                      <CartesianGrid strokeDasharray="3 3" />
                      <XAxis dataKey="date" interval={Math.floor(chartData.length / 7)} />
                      <YAxis allowDecimals={false} />
                      <RTooltip />
                      <Legend />
                      <Line type="monotone" dataKey="Planned" dot={false} strokeWidth={2} />
                      <Line type="monotone" dataKey="Actual" dot={false} strokeWidth={2} />
                    </LineChart>
                  </ResponsiveContainer>
                ) : (
                  <div className="text-sm text-slate-500">Create a plan to see the chart.</div>
                )}
              </CardContent>
            </Card>
          </TabsContent>
          <TabsContent value="calendar">
            <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
              {days.map((d) => {
                const met = d.actual >= d.planned && d.planned > 0;
                return (
                  <motion.div
                    key={d.date}
                    initial={{ opacity: 0, y: 8 }}
                    animate={{ opacity: 1, y: 0 }}
                    className={`rounded-2xl border p-4 shadow-sm ${met ? "ring-2 ring-green-500/40" : ""}`}
                  >
                    <div className="mb-2 flex items-center justify-between">
                      <div className="font-semibold">{formatPretty(d.date)}</div>
                      <TooltipProvider>
                        <Tooltip>
                          <TooltipTrigger className="text-xs text-slate-500">Planned</TooltipTrigger>
                          <TooltipContent>
                            <p>Pages planned for this day</p>
                          </TooltipContent>
                        </Tooltip>
                      </TooltipProvider>
                    </div>
                    <div className="mb-3 text-sm text-slate-600">
                      Target: <span className="font-semibold">{d.planned}</span> pages
                    </div>
                    <div className="flex items-end gap-2">
                      <div className="flex-1 space-y-2">
                        <Label htmlFor={`a-${d.date}`} className="text-xs">
                          Pages studied
                        </Label>
                        <Input
                          id={`a-${d.date}`}
                          type="number"
                          min={0}
                          value={d.actual}
                          onChange={(e) => updateActual(d.date, Number(e.target.value))}
                        />
                      </div>
                      <div className="flex flex-col gap-2">
                        <Button size="sm" variant="secondary" onClick={() => bumpActual(d.date, d.planned)}>
                          +{d.planned}
                        </Button>
                        <Button size="sm" variant="outline" onClick={() => bumpActual(d.date, 5)}>
                          +5
                        </Button>
                      </div>
                    </div>
                    {met && (
                      <div className="mt-3 flex items-center gap-2 text-green-700">
                        <CheckCircle2 className="h-4 w-4" />
                        <span className="text-sm">Great job! You hit today’s target 🎉</span>
                      </div>
                    )}
                  </motion.div>
                );
              })}
            </div>
          </TabsContent>
        </Tabs>

        <footer className="pt-4 text-center text-xs text-slate-500">
          Data is stored locally in your browser. Coming next: user accounts and cloud sync.
        </footer>
      </div>
    </div>
  );
}

function StreakBadge({ days }: { days: DayPlan[] }) {
  const today = toYMD(new Date());
  const upToToday = days.filter((d) => d.date <= today);
  let streak = 0;
  for (let i = upToToday.length - 1; i >= 0; i--) {
    const d = upToToday[i];
    if (d.actual >= d.planned && d.planned > 0) streak++;
    else break;
  }
  const best = (() => {
    let bestStreak = 0;
    let cur = 0;
    for (const d of upToToday) {
      if (d.actual >= d.planned && d.planned > 0) cur++;
      else {
        bestStreak = Math.max(bestStreak, cur);
        cur = 0;
      }
    }
    return Math.max(bestStreak, cur);
  })();

  return (
    <div className="flex items-center justify-between rounded-2xl border p-4">
      <div className="space-y-1">
        <div className="text-sm text-slate-600">Current streak</div>
        <div className="text-2xl font-bold">{streak}🔥</div>
      </div>
      <div className="h-10 w-px bg-slate-200" />
      <div className="space-y-1">
        <div className="text-sm text-slate-600">Best streak</div>
        <div className="text-2xl font-bold">{best}</div>
      </div>
    </div>
  );
}