"use client";

import type { JSX } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import Link from "next/link";
import { useTranslations } from "next-intl";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { Button } from "@/shared/components/ui/button";
import { Skeleton } from "@/shared/components/ui/skeleton";
import { cn } from "@/shared/lib/utils";
import { getCalendarEventsAction } from "../actions-calendar";
import type { LessonPlanCalendarEvent } from "../data-access-calendar";

type ViewMode = "week" | "month";

interface Props {
  initialTeacherId: string;
}

const WEEK_DAY_KEYS = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"] as const;

/** 计算所在周的第一天（周日为起点） */
function getWeekStart(date: Date): Date {
  const d = new Date(date);
  d.setHours(0, 0, 0, 0);
  d.setDate(d.getDate() - d.getDay());
  return d;
}

/** 计算所在月的第一天 */
function getMonthStart(date: Date): Date {
  const d = new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0, 0);
  return d;
}

/** 计算所在月的最后一天 */
/** 生成日历网格（6 行 × 7 列 = 42 天，覆盖整月） */
function buildMonthGrid(monthDate: Date): Date[] {
  const start = getMonthStart(monthDate);
  const gridStart = getWeekStart(start);
  const days: Date[] = [];
  for (let i = 0; i < 42; i++) {
    const d = new Date(gridStart);
    d.setDate(gridStart.getDate() + i);
    days.push(d);
  }
  return days;
}

/** 生成周历网格（7 天） */
function buildWeekGrid(weekDate: Date): Date[] {
  const start = getWeekStart(weekDate);
  const days: Date[] = [];
  for (let i = 0; i < 7; i++) {
    const d = new Date(start);
    d.setDate(start.getDate() + i);
    days.push(d);
  }
  return days;
}

function formatDateKey(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 isSameDay(a: Date, b: Date): boolean {
  return (
    a.getFullYear() === b.getFullYear() &&
    a.getMonth() === b.getMonth() &&
    a.getDate() === b.getDate()
  );
}

/** 事件颜色映射 */
function getEventColor(eventType: LessonPlanCalendarEvent["eventType"]): string {
  switch (eventType) {
    case "created":
      return "bg-blue-100 text-blue-700 border-blue-200";
    case "updated":
      return "bg-slate-100 text-slate-700 border-slate-200";
    case "version_saved":
      return "bg-purple-100 text-purple-700 border-purple-200";
    case "submitted":
      return "bg-amber-100 text-amber-700 border-amber-200";
    case "published":
      return "bg-emerald-100 text-emerald-700 border-emerald-200";
    case "reviewed":
      return "bg-indigo-100 text-indigo-700 border-indigo-200";
    default:
      return "bg-slate-100 text-slate-700 border-slate-200";
  }
}

export function CalendarView({ initialTeacherId }: Props): JSX.Element {
  const t = useTranslations("lessonPreparation");
  const [viewMode, setViewMode] = useState<ViewMode>("week");
  const [cursor, setCursor] = useState<Date>(() => new Date());
  const [events, setEvents] = useState<LessonPlanCalendarEvent[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const today = useMemo(() => {
    const d = new Date();
    d.setHours(0, 0, 0, 0);
    return d;
  }, []);

  // 计算当前视图的起止日期
  const { startDate, endDate } = useMemo(() => {
    if (viewMode === "week") {
      const start = getWeekStart(cursor);
      const end = new Date(start);
      end.setDate(start.getDate() + 6);
      end.setHours(23, 59, 59, 999);
      return { startDate: start, endDate: end };
    }
    const start = getMonthStart(cursor);
    // 月视图扩展为 6 周网格
    const gridStart = getWeekStart(start);
    const gridEnd = new Date(gridStart);
    gridEnd.setDate(gridStart.getDate() + 41);
    gridEnd.setHours(23, 59, 59, 999);
    return { startDate: gridStart, endDate: gridEnd };
  }, [viewMode, cursor]);

  // 加载数据
  useEffect(() => {
    let cancelled = false;
    (async () => {
      setLoading(true);
      setError(null);
      try {
        const res = await getCalendarEventsAction({
          startDate: startDate.toISOString(),
          endDate: endDate.toISOString(),
        });
        if (cancelled) return;
        if (res.success && res.data) {
          setEvents(res.data.events);
        } else {
          setError(res.message ?? t("calendar.loadFailed"));
          setEvents([]);
        }
      } catch (e) {
        if (cancelled) return;
        console.error("[CalendarView] load failed", e);
        setError(t("calendar.loadFailed"));
        setEvents([]);
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [startDate, endDate, t]);

  // 按日期分组事件
  const grouped = useMemo(() => {
    const map = new Map<string, LessonPlanCalendarEvent[]>();
    for (const e of events) {
      const key = formatDateKey(e.occurredAt);
      const list = map.get(key) ?? [];
      list.push(e);
      map.set(key, list);
    }
    return map;
  }, [events]);

  const days = useMemo(() => {
    return viewMode === "week" ? buildWeekGrid(cursor) : buildMonthGrid(cursor);
  }, [viewMode, cursor]);

  const handlePrev = useCallback(() => {
    setCursor((prev) => {
      const d = new Date(prev);
      if (viewMode === "week") {
        d.setDate(d.getDate() - 7);
      } else {
        d.setMonth(d.getMonth() - 1);
      }
      return d;
    });
  }, [viewMode]);

  const handleNext = useCallback(() => {
    setCursor((prev) => {
      const d = new Date(prev);
      if (viewMode === "week") {
        d.setDate(d.getDate() + 7);
      } else {
        d.setMonth(d.getMonth() + 1);
      }
      return d;
    });
  }, [viewMode]);

  const handleToday = useCallback(() => {
    setCursor(new Date());
  }, []);

  const title = useMemo(() => {
    const y = cursor.getFullYear();
    const m = cursor.getMonth() + 1;
    if (viewMode === "month") {
      return `${y}-${String(m).padStart(2, "0")}`;
    }
    const ws = getWeekStart(cursor);
    const we = new Date(ws);
    we.setDate(ws.getDate() + 6);
    return `${ws.getFullYear()}-${String(ws.getMonth() + 1).padStart(2, "0")}-${String(ws.getDate()).padStart(2, "0")} ~ ${we.getFullYear()}-${String(we.getMonth() + 1).padStart(2, "0")}-${String(we.getDate()).padStart(2, "0")}`;
  }, [cursor, viewMode]);

  // 隐藏未使用变量 lint 警告（initialTeacherId 由 Server Component 注入以便未来扩展）
  void initialTeacherId;

  return (
    <div className="space-y-4">
      {/* 工具栏 */}
      <div className="flex flex-wrap items-center justify-between gap-2">
        <div className="flex items-center gap-2">
          <Button variant="outline" size="icon" onClick={handlePrev} aria-label={t("calendar.prev")}>
            <ChevronLeft className="h-4 w-4" />
          </Button>
          <Button variant="outline" size="icon" onClick={handleNext} aria-label={t("calendar.next")}>
            <ChevronRight className="h-4 w-4" />
          </Button>
          <Button variant="outline" size="sm" onClick={handleToday}>
            {t("calendar.today")}
          </Button>
          <span className="ml-2 text-sm font-medium">{title}</span>
        </div>
        <div className="flex items-center gap-1 border rounded-md p-0.5">
          <Button
            variant={viewMode === "week" ? "default" : "ghost"}
            size="sm"
            onClick={() => setViewMode("week")}
          >
            {t("calendar.weekView")}
          </Button>
          <Button
            variant={viewMode === "month" ? "default" : "ghost"}
            size="sm"
            onClick={() => setViewMode("month")}
          >
            {t("calendar.monthView")}
          </Button>
        </div>
      </div>

      {/* 错误提示 */}
      {error !== null && (
        <div className="rounded-md border border-destructive/30 bg-destructive/5 p-3 text-sm text-destructive">
          {error}
        </div>
      )}

      {/* 周历视图 */}
      {viewMode === "week" ? (
        <WeekGrid
          days={days}
          grouped={grouped}
          today={today}
          loading={loading}
          t={t}
        />
      ) : (
        <MonthGrid
          days={days}
          cursor={cursor}
          grouped={grouped}
          today={today}
          loading={loading}
          t={t}
        />
      )}
    </div>
  );
}

interface GridProps {
  days: Date[];
  grouped: Map<string, LessonPlanCalendarEvent[]>;
  today: Date;
  loading: boolean;
  t: ReturnType<typeof useTranslations>;
}

function WeekGrid({ days, grouped, today, loading, t }: GridProps): JSX.Element {
  return (
    <div className="grid grid-cols-7 gap-2">
      {days.map((d) => {
        const key = formatDateKey(d);
        const dayEvents = grouped.get(key) ?? [];
        const isToday = isSameDay(d, today);
        return (
          <div key={key} className="flex flex-col">
            <div
              className={cn(
                "text-center text-xs font-medium pb-1 border-b",
                isToday ? "text-primary border-primary" : "text-muted-foreground border-border",
              )}
            >
              {t(`calendar.weekDays.${WEEK_DAY_KEYS[d.getDay()]}`)}
              <span className="ml-1">{d.getDate()}</span>
            </div>
            <div className="flex-1 min-h-[200px] space-y-1 pt-1">
              {loading ? (
                <Skeleton className="h-8 w-full" />
              ) : dayEvents.length === 0 ? (
                <p className="text-xs text-muted-foreground/60 italic mt-2 text-center">
                  {t("calendar.noEvents")}
                </p>
              ) : (
                dayEvents.slice(0, 6).map((e) => <EventChip key={e.id} event={e} t={t} />)
              )}
              {dayEvents.length > 6 && (
                <p className="text-xs text-muted-foreground">+{dayEvents.length - 6}</p>
              )}
            </div>
          </div>
        );
      })}
    </div>
  );
}

function MonthGrid({ days, cursor, grouped, today, loading, t }: GridProps & { cursor: Date }): JSX.Element {
  return (
    <div className="border rounded-md overflow-hidden">
      {/* 表头 */}
      <div className="grid grid-cols-7 bg-muted/40">
        {WEEK_DAY_KEYS.map((dk) => (
          <div key={dk} className="text-center text-xs font-medium py-2 border-r last:border-r-0">
            {t(`calendar.weekDays.${dk}`)}
          </div>
        ))}
      </div>
      {/* 日期格子 */}
      <div className="grid grid-cols-7">
        {days.map((d, i) => {
          const key = formatDateKey(d);
          const dayEvents = grouped.get(key) ?? [];
          const isCurrentMonth = d.getMonth() === cursor.getMonth();
          const isToday = isSameDay(d, today);
          return (
            <div
              key={key}
              className={cn(
                "min-h-[120px] border-r border-b p-1",
                (i + 1) % 7 === 0 && "border-r-0",
                i >= days.length - 7 && "border-b-0",
                !isCurrentMonth && "bg-muted/20",
              )}
            >
              <div
                className={cn(
                  "text-xs font-medium mb-1 inline-flex items-center justify-center w-6 h-6 rounded-full",
                  isToday ? "bg-primary text-primary-foreground" : "text-muted-foreground",
                  !isCurrentMonth && "opacity-40",
                )}
              >
                {d.getDate()}
              </div>
              <div className="space-y-1">
                {loading ? (
                  <Skeleton className="h-4 w-full" />
                ) : (
                  dayEvents.slice(0, 3).map((e) => <EventChip key={e.id} event={e} t={t} compact />)
                )}
                {dayEvents.length > 3 && (
                  <p className="text-xs text-muted-foreground">+{dayEvents.length - 3}</p>
                )}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

interface EventChipProps {
  event: LessonPlanCalendarEvent;
  t: ReturnType<typeof useTranslations>;
  compact?: boolean;
}

function EventChip({ event, t, compact }: EventChipProps): JSX.Element {
  const color = getEventColor(event.eventType);
  const href = `/teacher/lesson-plans/${event.planId}/edit`;
  const label = t(`calendar.eventType.${event.eventType}`);
  const meta =
    event.eventType === "version_saved" && event.versionNo !== undefined
      ? t("calendar.eventMeta", { versionNo: event.versionNo })
      : null;

  return (
    <Link
      href={href}
      className={cn(
        "block rounded border px-1.5 py-0.5 text-xs transition-colors hover:opacity-80",
        color,
        compact && "truncate",
      )}
      title={`${label}：${event.title}${meta ?? ""}`}
    >
      <span className="font-medium">{label}</span>
      <span className="mx-1 opacity-60">·</span>
      <span className="truncate">{event.title}</span>
      {meta !== null && <span className="ml-1 opacity-70">{meta}</span>}
    </Link>
  );
}
