"use client";

import Link from "next/link";
import { useActionState, useMemo, useState } from "react";
import {
  format,
  startOfMonth,
  endOfMonth,
  startOfWeek,
  endOfWeek,
  addDays,
  addMonths,
  subMonths,
  isSameMonth,
  isSameDay,
  isToday,
  isAfter,
  startOfDay,
} from "date-fns";
import { pl } from "date-fns/locale";
import { Activity, ChevronLeft, ChevronRight, Dumbbell, Sparkles } from "lucide-react";
import { generateDashboardAnalysisAction } from "@/app/ai/actions";
import { formatDate, formatDistance, formatDuration, formatPace } from "@/lib/format";
import type { SerializedAiAnalysis } from "@/lib/models/analysis";

export type DayRun = {
  id: string;
  name: string;
  startTime: string;
  distanceM: number;
  durationSec: number;
  avgPaceSecPerKm: number;
};

export type DayWorkout = {
  id: string;
  name: string;
  date: string;
  exerciseCount: number;
};

type Props = {
  analyses: SerializedAiAnalysis[];
  runs: DayRun[];
  workouts: DayWorkout[];
};

function dayKey(date: Date): string {
  return `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
}

export function DashboardAnalysisCard({ analyses, runs, workouts }: Props) {
  const [state, formAction, pending] = useActionState(generateDashboardAnalysisAction, null);

  // Map each calendar day to its (latest) analysis. Selecting a day is a pure
  // local lookup, no server round-trip.
  const byDay = useMemo(() => {
    const map = new Map<string, SerializedAiAnalysis>();
    for (const a of analyses) {
      const key = dayKey(new Date(a.createdAt));
      if (!map.has(key)) map.set(key, a); // analyses are newest-first
    }
    return map;
  }, [analyses]);

  const [currentMonth, setCurrentMonth] = useState(() => new Date());
  const [selectedDate, setSelectedDate] = useState<Date>(() => new Date());

  const runDays = useMemo(
    () => new Set(runs.map((r) => dayKey(new Date(r.startTime)))),
    [runs]
  );
  const workoutDays = useMemo(
    () => new Set(workouts.map((w) => dayKey(new Date(w.date)))),
    [workouts]
  );

  const todayStart = startOfDay(new Date());

  const monthStart = startOfMonth(currentMonth);
  const monthEnd = endOfMonth(monthStart);
  const calendarStart = startOfWeek(monthStart, { weekStartsOn: 1 });
  const calendarEnd = endOfWeek(monthEnd, { weekStartsOn: 1 });

  const days: Date[] = [];
  let cursor = calendarStart;
  while (cursor <= calendarEnd) {
    days.push(cursor);
    cursor = addDays(cursor, 1);
  }

  const weekDays = ["Pn", "Wt", "Śr", "Cz", "Pt", "Sb", "Nd"];

  const selectedAnalysis = byDay.get(dayKey(selectedDate)) ?? null;
  const viewingToday = isToday(selectedDate);

  const dayRuns = runs.filter((r) => isSameDay(new Date(r.startTime), selectedDate));
  const dayWorkouts = workouts.filter((w) => isSameDay(new Date(w.date), selectedDate));

  return (
    <section className="flex flex-col gap-4 rounded-lg border border-muted/40 bg-surface p-4">
      <div className="flex items-center justify-between">
        <h2 className="flex items-center gap-1.5 text-lg font-semibold text-fg">
          <Sparkles size={18} className="text-accent" />
          Kondycja treningowa
        </h2>
        {viewingToday && (
          <form action={formAction}>
            <button
              type="submit"
              disabled={pending}
              className="rounded-md bg-accent px-3 py-1.5 text-sm font-semibold text-fg transition-opacity hover:opacity-90 disabled:opacity-50"
            >
              {pending ? "Analizuję..." : selectedAnalysis ? "Odśwież analizę" : "Generuj analizę"}
            </button>
          </form>
        )}
      </div>

      {state && "error" in state ? <p className="text-sm text-accent">{state.error}</p> : null}

      <div className="flex flex-col gap-4 sm:flex-row">
        <div className="min-w-[280px]">
          <div className="mb-2 flex items-center justify-between">
            <button
              type="button"
              onClick={() => setCurrentMonth(subMonths(currentMonth, 1))}
              className="rounded p-1 text-fg/60 transition-colors hover:text-fg"
            >
              <ChevronLeft size={16} />
            </button>
            <span className="text-sm font-medium capitalize text-fg">
              {format(currentMonth, "LLLL yyyy", { locale: pl })}
            </span>
            <button
              type="button"
              onClick={() => setCurrentMonth(addMonths(currentMonth, 1))}
              className="rounded p-1 text-fg/60 transition-colors hover:text-fg"
            >
              <ChevronRight size={16} />
            </button>
          </div>

          <div className="grid grid-cols-7 gap-1 text-center text-xs text-fg/50">
            {weekDays.map((d) => (
              <div key={d} className="py-1">
                {d}
              </div>
            ))}
          </div>

          <div className="grid grid-cols-7 gap-1">
            {days.map((d, i) => {
              const key = dayKey(d);
              const inMonth = isSameMonth(d, monthStart);
              const today = isToday(d);
              const future = isAfter(startOfDay(d), todayStart);
              const selectable = !future;
              const selected = isSameDay(d, selectedDate);

              const hasRun = runDays.has(key);
              const hasWorkout = workoutDays.has(key);
              const hasAnalysis = byDay.has(key);

              return (
                <button
                  type="button"
                  key={i}
                  onClick={() => selectable && setSelectedDate(d)}
                  disabled={!selectable}
                  className={[
                    "relative flex h-8 w-full items-center justify-center rounded text-xs transition-colors",
                    !inMonth && "opacity-30",
                    selectable && !selected && "cursor-pointer text-fg hover:bg-accent/20",
                    selected && "bg-accent font-semibold text-fg",
                    !selectable && "cursor-not-allowed text-fg/30",
                    today && !selected && "ring-1 ring-accent/50",
                  ]
                    .filter(Boolean)
                    .join(" ")}
                >
                  {d.getDate()}
                  {!selected && (hasRun || hasWorkout || hasAnalysis) && (
                    <span className="absolute bottom-0.5 left-1/2 flex -translate-x-1/2 gap-0.5">
                      {hasRun && <span className="h-1 w-1 rounded-full bg-[#5b9bd5]" />}
                      {hasWorkout && <span className="h-1 w-1 rounded-full bg-[#70ad47]" />}
                      {hasAnalysis && <span className="h-1 w-1 rounded-full bg-accent" />}
                    </span>
                  )}
                </button>
              );
            })}
          </div>

          <div className="mt-3 flex flex-wrap items-center gap-x-3 gap-y-1 text-[11px] text-fg/55">
            <span className="flex items-center gap-1">
              <span className="h-1.5 w-1.5 rounded-full bg-[#5b9bd5]" /> Bieg
            </span>
            <span className="flex items-center gap-1">
              <span className="h-1.5 w-1.5 rounded-full bg-[#70ad47]" /> Siłownia
            </span>
            <span className="flex items-center gap-1">
              <span className="h-1.5 w-1.5 rounded-full bg-accent" /> Analiza
            </span>
          </div>

          <div className="mt-4 flex flex-col gap-1.5">
            <p className="text-xs font-medium text-fg/50">
              Treningi · {format(selectedDate, "d MMM yyyy", { locale: pl })}
            </p>
            {dayRuns.length === 0 && dayWorkouts.length === 0 ? (
              <p className="text-xs text-fg/40">Brak treningów tego dnia.</p>
            ) : (
              <ul className="flex flex-col gap-1.5">
                {dayRuns.map((run) => (
                  <li key={run.id}>
                    <Link
                      href={`/running/${run.id}`}
                      className="flex items-center gap-2 rounded-md border border-muted/40 bg-bg/40 px-2.5 py-1.5 transition-colors hover:border-accent/60"
                    >
                      <Activity size={14} className="shrink-0 text-accent" />
                      <span className="min-w-0 flex-1">
                        <span className="block truncate text-xs font-medium text-fg">
                          {run.name}
                        </span>
                        <span className="block text-[11px] text-fg/55">
                          {formatDistance(run.distanceM)} · {formatDuration(run.durationSec)} ·{" "}
                          {formatPace(run.avgPaceSecPerKm)}
                        </span>
                      </span>
                    </Link>
                  </li>
                ))}
                {dayWorkouts.map((workout) => (
                  <li key={workout.id}>
                    <Link
                      href={`/strength/${workout.id}`}
                      className="flex items-center gap-2 rounded-md border border-muted/40 bg-bg/40 px-2.5 py-1.5 transition-colors hover:border-accent/60"
                    >
                      <Dumbbell size={14} className="shrink-0 text-accent" />
                      <span className="min-w-0 flex-1">
                        <span className="block truncate text-xs font-medium text-fg">
                          {workout.name}
                        </span>
                        <span className="block text-[11px] text-fg/55">
                          {workout.exerciseCount}{" "}
                          {workout.exerciseCount === 1 ? "ćwiczenie" : "ćwiczeń"}
                        </span>
                      </span>
                    </Link>
                  </li>
                ))}
              </ul>
            )}
          </div>
        </div>

        <div className="flex-1">
          {selectedAnalysis ? (
            <div className="flex flex-col gap-2">
              <p className="text-xs font-medium text-fg/50">
                {format(selectedDate, "d MMMM yyyy", { locale: pl })}
              </p>
              <p className="text-sm text-fg/90">{selectedAnalysis.summary}</p>
              {selectedAnalysis.tips.length > 0 && (
                <ul className="list-disc pl-5 text-sm text-fg/80">
                  {selectedAnalysis.tips.map((tip, index) => (
                    <li key={index}>{tip}</li>
                  ))}
                </ul>
              )}
              <p className="text-xs text-fg/40">
                {formatDate(selectedAnalysis.createdAt)} · {selectedAnalysis.model}
              </p>
            </div>
          ) : viewingToday ? (
            <p className="text-sm text-fg/60">
              Brak analizy na dziś. Wygeneruj kompleksową analizę kondycji łączącą dane biegowe,
              siłowe, HRV i sen.
            </p>
          ) : (
            <p className="text-sm text-fg/60">
              Brak analizy AI dla {format(selectedDate, "d MMMM yyyy", { locale: pl })}.
            </p>
          )}
        </div>
      </div>
    </section>
  );
}
