"use client";

import { useEffect, useState, useCallback, useMemo } from "react";
import { useSearchParams } from "next/navigation";
import { createClient } from "@/lib/supabase/client";
import Card, { CardHeader } from "@/components/ui/Card";
import Button from "@/components/ui/Button";
import Badge, { statusTone } from "@/components/ui/Badge";
import Modal from "@/components/ui/Modal";
import Spinner from "@/components/ui/Spinner";
import Chips from "@/components/ui/Chips";
import { Field, Input, Textarea } from "@/components/ui/Input";
import { Select } from "@/components/ui/Select";
import { Table, Td, EmptyRow } from "@/components/ui/Table";
import { useToast } from "@/components/ui/Toast";
import { formatDate, formatDateTime, toLocalInput } from "@/lib/format";
import QrCheckinModal from "@/components/QrCheckinModal";
import {
  Plus,
  Pencil,
  Trash2,
  Search,
  Sparkles,
  MapPin,
  Calendar as CalendarIcon,
  Award,
  Check,
  ChevronLeft,
  ChevronRight,
  ExternalLink,
  Image as ImageIcon,
  QrCode,
  Users,
  FileDown,
  FileSpreadsheet,
  ClipboardList,
} from "lucide-react";

type Program = {
  id: string;
  title: string;
  description: string;
  venue: string | null;
  start_at: string;
  end_at: string | null;
  slots: number;
  merit_value: number;
  status: "open" | "closed" | "completed";
  image_url: string | null;
  program_skills?: { skills: { id: string; name: string } }[];
  slots_left?: number;
};
type Skill = { id: string; name: string };

type AttendanceRow = {
  volunteer_id: string;
  full_name: string;
  matric_no: string | null;
  email: string | null;
  checked_in_at: string;
};

const empty = {
  id: "",
  title: "",
  description: "",
  venue: "",
  start_at: "",
  end_at: "",
  slots: 20,
  merit_value: 10,
  status: "open" as Program["status"],
  image_url: "",
};

function useIsMobileViewport() {
  const [isMobile, setIsMobile] = useState(false);
  useEffect(() => {
    const check = () => setIsMobile(window.innerWidth < 768);
    check();
    window.addEventListener("resize", check);
    return () => window.removeEventListener("resize", check);
  }, []);
  return isMobile;
}

export default function ProgramsPage() {
  const supabase = createClient();
  const searchParams = useSearchParams();
  const { notify } = useToast();
  const isViewportMobile = useIsMobileViewport();
  const isPreviewMobile = searchParams.get("preview") === "mobile";
  const isMobile = isViewportMobile || isPreviewMobile;

  const [loading, setLoading] = useState(true);
  const [userRole, setUserRole] = useState<"admin" | "volunteer">("volunteer");
  const [userId, setUserId] = useState("");
  const [studentSkills, setStudentSkills] = useState<string[]>([]);

  // Common data
  const [programs, setPrograms] = useState<Program[]>([]);
  const [skills, setSkills] = useState<Skill[]>([]);
  const [applications, setApplications] = useState<any[]>([]);
  // Map of program_id -> attended count, used for the Attendance column badge
  const [attendanceCounts, setAttendanceCounts] = useState<Record<string, number>>({});

  // Admin Modal states
  const [open, setOpen] = useState(false);
  const [saving, setSaving] = useState(false);
  const [form, setForm] = useState(empty);
  const [selectedSkills, setSelectedSkills] = useState<string[]>([]);

  // Student details modal
  const [detailsOpen, setDetailsOpen] = useState(false);
  const [selectedProgram, setSelectedProgram] = useState<Program | null>(null);

  // QR attendance check-in modal (admin only)
  const [qrProgram, setQrProgram] = useState<{ id: string; title: string } | null>(null);

  // Attendance VIEW modal (admin only) — list + export
  const [attendanceProgram, setAttendanceProgram] = useState<Program | null>(null);
  const [attendanceRows, setAttendanceRows] = useState<AttendanceRow[]>([]);
  const [attendanceLoading, setAttendanceLoading] = useState(false);
  const [attendanceSearch, setAttendanceSearch] = useState("");

  // View state: list vs calendar
  const [viewMode, setViewMode] = useState<"list" | "calendar">("list");

  // Calendar states
  const [currentDate, setCurrentDate] = useState(new Date());

  // Filters
  const [search, setSearch] = useState("");
  const [tab, setTab] = useState<"all" | "upcoming" | "ongoing" | "completed">("all");
  const [skillFilter, setSkillFilter] = useState("");

  const load = useCallback(async () => {
    const { data: userRes } = await supabase.auth.getUser();
    if (!userRes.user) return;

    setUserId(userRes.user.id);

    const { data: profile } = await supabase
      .from("profiles")
      .select("role")
      .eq("id", userRes.user.id)
      .single();

    const role = profile?.role || "volunteer";
    setUserRole(role);

    const [progsRes, skillsRes, appsRes, mySkillsRes, slotsTakenRes, attendanceRes] = await Promise.all([
      supabase
        .from("programs")
        .select("*, program_skills(skills(id, name))")
        .order("start_at", { ascending: false }),
      supabase.from("skills").select("id, name").order("name"),
      supabase
        .from("applications")
        .select("*")
        .eq("volunteer_id", userRes.user.id),
      supabase
        .from("volunteer_skills")
        .select("skills(name)")
        .eq("volunteer_id", userRes.user.id),
      supabase.from("program_slots_taken").select("*"),
      // Attendance counts per program, only meaningful for admin but cheap
      // enough to fetch regardless — used for the badge next to "Status".
      supabase.from("attendance").select("program_id"),
    ]);

    const slotsMap = new Map(slotsTakenRes.data?.map((x: any) => [x.program_id, x.approved_count]) ?? []);
    const loadedPrograms = ((progsRes.data as Program[]) ?? []).map((p) => {
      const taken = slotsMap.get(p.id) ?? 0;
      return {
        ...p,
        slots_left: Math.max(0, p.slots - taken),
      };
    });

    const counts: Record<string, number> = {};
    (attendanceRes.data ?? []).forEach((row: any) => {
      counts[row.program_id] = (counts[row.program_id] ?? 0) + 1;
    });
    setAttendanceCounts(counts);

    setPrograms(loadedPrograms);
    setSkills((skillsRes.data as Skill[]) ?? []);
    setApplications(appsRes.data ?? []);
    setStudentSkills(
      (mySkillsRes.data ?? []).map((row: any) => row.skills?.name).filter(Boolean)
    );

    setLoading(false);
  }, [supabase]);

  useEffect(() => {
    load();
  }, [load]);

  // Load the attendance list whenever an attendance program is selected
  useEffect(() => {
    if (!attendanceProgram) {
      setAttendanceRows([]);
      return;
    }
    (async () => {
      setAttendanceLoading(true);
      const { data, error } = await supabase
        .from("attendance")
        .select("volunteer_id, checked_in_at, profiles!volunteer_id(full_name, matric_no, email)")
        .eq("program_id", attendanceProgram.id)
        .order("checked_in_at", { ascending: true });

      if (error) {
        notify(error.message, "error");
        setAttendanceRows([]);
        setAttendanceLoading(false);
        return;
      }

      const rows: AttendanceRow[] = (data ?? []).map((row: any) => ({
        volunteer_id: row.volunteer_id,
        full_name: row.profiles?.full_name ?? "Unknown",
        matric_no: row.profiles?.matric_no ?? null,
        email: row.profiles?.email ?? null,
        checked_in_at: row.checked_in_at,
      }));
      setAttendanceRows(rows);
      setAttendanceLoading(false);
    })();
  }, [attendanceProgram, supabase, notify]);

  const filteredAttendanceRows = useMemo(() => {
    const q = attendanceSearch.trim().toLowerCase();
    if (!q) return attendanceRows;
    return attendanceRows.filter(
      (r) =>
        r.full_name.toLowerCase().includes(q) ||
        (r.matric_no ?? "").toLowerCase().includes(q) ||
        (r.email ?? "").toLowerCase().includes(q)
    );
  }, [attendanceRows, attendanceSearch]);

  // Export the current attendance list (respecting the active search filter)
  // to a landscape PDF table.
  async function exportAttendancePdf() {
    if (!attendanceProgram) return;
    const { jsPDF } = await import("jspdf");
    const autoTableModule = await import("jspdf-autotable");
    const autoTable = (autoTableModule as any).default ?? autoTableModule;

    const doc = new jsPDF({ orientation: "landscape", unit: "pt", format: "a4" });
    const emerald: [number, number, number] = [15, 110, 86];

    doc.setFont("helvetica", "bold");
    doc.setFontSize(16);
    doc.setTextColor(...emerald);
    doc.text(`Attendance — ${attendanceProgram.title}`, 40, 40);

    doc.setFont("helvetica", "normal");
    doc.setFontSize(10);
    doc.setTextColor(90, 90, 90);
    doc.text(
      `${formatDate(attendanceProgram.start_at)}  ·  ${attendanceProgram.venue ?? "Online"}  ·  ${filteredAttendanceRows.length} attendee(s)`,
      40,
      58
    );

    autoTable(doc, {
      startY: 75,
      head: [["#", "Full Name", "Matric No.", "Email", "Checked In At"]],
      body: filteredAttendanceRows.map((r, i) => [
        i + 1,
        r.full_name,
        r.matric_no ?? "—",
        r.email ?? "—",
        formatDateTime(r.checked_in_at),
      ]),
      headStyles: { fillColor: emerald, textColor: 255, fontStyle: "bold" },
      styles: { fontSize: 9, cellPadding: 6 },
      alternateRowStyles: { fillColor: [248, 246, 240] },
    });

    const safeName = attendanceProgram.title.replace(/[^a-z0-9]+/gi, "_").toLowerCase();
    doc.save(`attendance_${safeName}.pdf`);
  }

  // Export the current attendance list to an .xlsx workbook.
  async function exportAttendanceExcel() {
    if (!attendanceProgram) return;
    const XLSX = await import("xlsx");

    const sheetData = filteredAttendanceRows.map((r, i) => ({
      "#": i + 1,
      "Full Name": r.full_name,
      "Matric No.": r.matric_no ?? "",
      Email: r.email ?? "",
      "Checked In At": formatDateTime(r.checked_in_at),
    }));

    const worksheet = XLSX.utils.json_to_sheet(sheetData);
    worksheet["!cols"] = [{ wch: 4 }, { wch: 28 }, { wch: 16 }, { wch: 28 }, { wch: 22 }];

    const workbook = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(workbook, worksheet, "Attendance");

    const safeName = attendanceProgram.title.replace(/[^a-z0-9]+/gi, "_").toLowerCase();
    XLSX.writeFile(workbook, `attendance_${safeName}.xlsx`);
  }

  // Google Calendar URL Generator
  function getGoogleCalendarUrl(p: Program) {
    const start = new Date(p.start_at).toISOString().replace(/[-:]/g, "").split(".")[0] + "Z";
    const end = p.end_at
      ? new Date(p.end_at).toISOString().replace(/[-:]/g, "").split(".")[0] + "Z"
      : new Date(new Date(p.start_at).getTime() + 2 * 60 * 60 * 1000)
          .toISOString()
          .replace(/[-:]/g, "")
          .split(".")[0] + "Z";

    const params = new URLSearchParams({
      action: "TEMPLATE",
      text: p.title,
      dates: `${start}/${end}`,
      details: p.description,
      location: p.venue || "Pusat Islam UPSI",
    });
    return `https://calendar.google.com/calendar/render?${params.toString()}`;
  }

  // Admin Save handler
  async function save(e: React.FormEvent) {
    e.preventDefault();
    setSaving(true);

    const payload = {
      title: form.title,
      description: form.description,
      venue: form.venue || null,
      start_at: new Date(form.start_at).toISOString(),
      end_at: form.end_at ? new Date(form.end_at).toISOString() : null,
      slots: Number(form.slots),
      merit_value: Number(form.merit_value),
      status: form.status,
      image_url: form.image_url || null,
    };

    let programId = form.id;
    if (form.id) {
      const { error } = await supabase.from("programs").update(payload).eq("id", form.id);
      if (error) return fail(error.message);
    } else {
      const { data, error } = await supabase
        .from("programs")
        .insert({ ...payload, created_by: userId })
        .select("id")
        .single();
      if (error || !data) return fail(error?.message ?? "Could not create program.");
      programId = data.id;
    }

    // Reset and re-insert required skills
    await supabase.from("program_skills").delete().eq("program_id", programId);
    if (selectedSkills.length) {
      const rows = selectedSkills.map((skill_id) => ({ program_id: programId, skill_id }));
      const { error } = await supabase.from("program_skills").insert(rows);
      if (error) return fail(error.message);
    }

    notify(form.id ? "Program updated." : "Program created.");
    setOpen(false);
    setSaving(false);
    load();
  }

  function fail(msg: string) {
    notify(msg, "error");
    setSaving(false);
  }

  async function remove(p: Program) {
    if (!confirm(`Delete "${p.title}"? This cannot be undone.`)) return;
    const { error } = await supabase.from("programs").delete().eq("id", p.id);
    if (error) return notify(error.message, "error");
    notify("Program deleted.");
    load();
  }

  function openCreate() {
    setForm(empty);
    setSelectedSkills([]);
    setOpen(true);
  }

  async function openEdit(p: Program) {
    setForm({
      ...p,
      venue: p.venue ?? "",
      start_at: toLocalInput(p.start_at),
      end_at: toLocalInput(p.end_at),
      image_url: p.image_url ?? "",
    });
    const { data } = await supabase.from("program_skills").select("skill_id").eq("program_id", p.id);
    setSelectedSkills((data ?? []).map((r) => r.skill_id));
    setOpen(true);
  }

  function toggleSkill(id: string) {
    setSelectedSkills((s) => (s.includes(id) ? s.filter((x) => x !== id) : [...s, id]));
  }

  // Student Apply handler
  async function applyToProgram(programId: string) {
    const { error } = await supabase.from("applications").insert({
      program_id: programId,
      volunteer_id: userId,
      status: "pending",
    });

    if (error) {
      notify(error.message, "error");
    } else {
      notify("Application submitted successfully! Awaiting admin approval.");
      setDetailsOpen(false);
      load();
    }
  }

  // Filters computed list
  const filtered = useMemo(() => {
    const q = search.trim().toLowerCase();
    const now = new Date();

    return programs.filter((p) => {
      const matchesSearch =
        !q ||
        p.title.toLowerCase().includes(q) ||
        p.description.toLowerCase().includes(q) ||
        (p.venue ?? "").toLowerCase().includes(q);

      const matchesSkill =
        !skillFilter ||
        (p.program_skills ?? []).some((ps) => ps.skills?.name === skillFilter);

      const start = new Date(p.start_at);
      const end = p.end_at ? new Date(p.end_at) : null;
      let matchesTab = true;
      if (tab === "upcoming") {
        matchesTab = p.status === "open" && start > now;
      } else if (tab === "ongoing") {
        matchesTab = p.status === "open" && start <= now && (!end || end >= now);
      } else if (tab === "completed") {
        matchesTab = p.status === "completed" || (end ? end < now : start < now && p.status !== "open");
      }

      return matchesSearch && matchesSkill && matchesTab;
    });
  }, [programs, search, skillFilter, tab]);

  // Monthly Calendar Dates Generator
  const calendarDays = useMemo(() => {
    const year = currentDate.getFullYear();
    const month = currentDate.getMonth();

    const firstDayIndex = new Date(year, month, 1).getDay();
    const lastDay = new Date(year, month + 1, 0).getDate();

    const days = [];

    // Empty cells before the 1st
    for (let i = 0; i < firstDayIndex; i++) {
      days.push(null);
    }

    // Active calendar days
    for (let i = 1; i <= lastDay; i++) {
      days.push(new Date(year, month, i));
    }

    return days;
  }, [currentDate]);

  function changeMonth(offset: number) {
    setCurrentDate(new Date(currentDate.getFullYear(), currentDate.getMonth() + offset, 1));
  }

  if (loading) return <Spinner label="Loading programs…" />;

  // RENDER ADMIN PROGRAM LIST
  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-extrabold text-ink">
            {userRole === "admin" ? "Manage Programs" : "Volunteer Programs"}
          </h1>
          <p className="text-sm text-muted">
            {userRole === "admin"
              ? "Create, edit, and maintain volunteer programs."
              : "Browse open events, match your skills, and register."}
          </p>
        </div>
        {userRole === "admin" && (
          <Button onClick={openCreate}>
            <Plus size={16} /> Create program
          </Button>
        )}
      </div>

      {/* Filters and View Toggles */}
      <div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
        {/* Search */}
        <div className="flex-1 max-w-sm relative">
          <Search size={16} className="absolute left-3 top-1/2 -translate-y-1/2 text-muted" />
          <Input
            className="pl-9 text-sm"
            placeholder="Search programs by name, venue..."
            value={search}
            onChange={(e) => setSearch(e.target.value)}
          />
        </div>

        {/* View Mode Toggle */}
        <div className="flex gap-2 bg-white p-1 rounded-card border border-sand-dark/60 shadow-sm shrink-0">
          <button
            onClick={() => setViewMode("list")}
            className={`px-3 py-1.5 text-xs font-bold rounded-card transition-all ${
              viewMode === "list" ? "bg-emerald text-white" : "text-muted hover:text-ink"
            }`}
          >
            List View
          </button>
          <button
            onClick={() => setViewMode("calendar")}
            className={`px-3 py-1.5 text-xs font-bold rounded-card transition-all ${
              viewMode === "calendar" ? "bg-emerald text-white" : "text-muted hover:text-ink"
            }`}
          >
            Calendar View
          </button>
        </div>
      </div>

      {viewMode === "list" ? (
        /* ================== LIST VIEW ================== */
        <div className="space-y-6">
          {/* Tabs */}
          <div className="flex border-b border-sand-dark/45">
            {(["all", "upcoming", "ongoing", "completed"] as const).map((t) => (
              <button
                key={t}
                onClick={() => setTab(t)}
                className={`border-b-2 px-4 py-2 text-xs font-bold uppercase tracking-wider transition-all ${
                  tab === t
                    ? "border-emerald text-emerald font-extrabold"
                    : "border-transparent text-muted hover:text-ink"
                }`}
              >
                {t}
              </button>
            ))}
          </div>

          {userRole === "admin" ? (
            /* Admin List Table */
            <Card>
              <Table headers={["Program Picture", "Title", "Date", "Venue", "Slots", "Merit", "Status", "Attendance", ""]}>
                {filtered.length ? (
                  filtered.map((p) => (
                    <tr key={p.id} className="hover:bg-sand/40">
                      <Td>
                        {p.image_url ? (
                          <img
                            src={p.image_url}
                            alt={p.title}
                            className="h-10 w-16 object-cover rounded-card border border-sand-dark"
                          />
                        ) : (
                          <div className="h-10 w-16 bg-sand flex items-center justify-center rounded-card border border-sand-dark text-[9px] text-muted font-bold">
                            No Photo
                          </div>
                        )}
                      </Td>
                      <Td className="font-semibold">{p.title}</Td>
                      <Td>{formatDate(p.start_at)}</Td>
                      <Td>{p.venue ?? "—"}</Td>
                      <Td>{p.slots_left !== undefined ? `${p.slots_left} / ${p.slots}` : p.slots}</Td>
                      <Td>{p.merit_value} MP</Td>
                      <Td>
                        <Badge tone={statusTone(p.status)}>{p.status}</Badge>
                      </Td>
                      <Td>
                        <button
                          onClick={() => setAttendanceProgram(p)}
                          className="inline-flex items-center gap-1.5 rounded-card border border-teal/30 bg-teal-light/40 px-2.5 py-1 text-xs font-bold text-teal hover:bg-teal-light/70 transition-colors"
                          title="View attendance"
                        >
                          <ClipboardList size={13} />
                          {attendanceCounts[p.id] ?? 0} attended
                        </button>
                      </Td>
                      <Td>
                        <div className="flex justify-end gap-1">
                          <button
                            onClick={() => setQrProgram({ id: p.id, title: p.title })}
                            className="rounded-card p-2 text-muted hover:bg-teal-50 hover:text-teal"
                            title="Attendance QR"
                          >
                            <QrCode size={16} />
                          </button>
                          <button
                            onClick={() => openEdit(p)}
                            className="rounded-card p-2 text-muted hover:bg-emerald-light hover:text-emerald"
                            title="Edit"
                          >
                            <Pencil size={16} />
                          </button>
                          <button
                            onClick={() => remove(p)}
                            className="rounded-card p-2 text-muted hover:bg-red-50 hover:text-error"
                            title="Delete"
                          >
                            <Trash2 size={16} />
                          </button>
                        </div>
                      </Td>
                    </tr>
                  ))
                ) : (
                  <EmptyRow colSpan={9} message="No programs found." />
                )}
              </Table>
            </Card>
          ) : (
            /* Student List Grid */
            <div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
              {filtered.length > 0 ? (
                filtered.map((p) => {
                  const alreadyApplied = applications.some((a) => a.program_id === p.id);
                  const appDetails = applications.find((a) => a.program_id === p.id);

                  // Check if there is a skill match
                  const reqSkills = (p.program_skills ?? []).map((ps) => ps.skills?.name).filter(Boolean);
                  const matchesSkills = reqSkills.some((s) => studentSkills.includes(s));

                  return (
                    <div
                      key={p.id}
                      onClick={() => {
                        setSelectedProgram(p);
                        setDetailsOpen(true);
                      }}
                      className="group flex flex-col justify-between rounded-card border border-sand-dark/60 bg-white shadow-card hover:shadow-cardHover hover:border-emerald/30 cursor-pointer overflow-hidden transition-all"
                    >
                      {/* Program Header Image */}
                      {p.image_url ? (
                        <img src={p.image_url} alt={p.title} className="h-40 w-full object-cover border-b border-sand-dark" />
                      ) : (
                        <div className="h-40 w-full bg-gradient-to-br from-emerald/10 to-teal/5 border-b border-sand-dark flex items-center justify-center text-emerald/35">
                          <ImageIcon size={48} />
                        </div>
                      )}

                      <div className="p-5 flex-1 flex flex-col justify-between">
                        <div>
                          <div className="flex justify-between items-start gap-2 mb-2">
                            <h3 className="text-sm font-bold text-ink group-hover:text-emerald transition-colors line-clamp-1">
                              {p.title}
                            </h3>
                            <Badge tone={statusTone(p.status)}>{p.status}</Badge>
                          </div>

                          <p className="text-xs text-muted line-clamp-2 mb-4 leading-relaxed">
                            {p.description}
                          </p>

                          <div className="space-y-1.5 text-xs text-muted mb-4">
                            <div className="flex items-center gap-2">
                              <MapPin size={12} className="text-emerald" />
                              <span className="truncate">{p.venue ?? "Online"}</span>
                            </div>
                            <div className="flex items-center gap-2">
                              <CalendarIcon size={12} className="text-emerald" />
                              <span>{formatDate(p.start_at)}</span>
                            </div>
                            <div className="flex items-center gap-2">
                              <Award size={12} className="text-emerald" />
                              <span className="font-semibold text-emerald">{p.merit_value} MP</span>
                            </div>
                          </div>
                        </div>

                        <div className="border-t border-sand-light pt-3 flex items-center justify-between">
                          <div className="flex flex-wrap gap-1">
                            {matchesSkills && (
                              <span className="inline-flex items-center gap-0.5 rounded-full bg-emerald-light px-2 py-0.5 text-[9px] font-bold text-emerald">
                                <Sparkles size={8} /> Skill Match
                              </span>
                            )}
                          </div>

                          {alreadyApplied ? (
                            <span
                              className={`inline-flex items-center gap-1 rounded-card px-2.5 py-1 text-xs font-bold ${
                                appDetails?.status === "approved"
                                  ? "bg-emerald-light text-emerald"
                                  : appDetails?.status === "rejected"
                                  ? "bg-red-50 text-error"
                                  : "bg-amber-50 text-warning"
                              }`}
                            >
                              {appDetails?.status === "approved" && <Check size={12} />}
                              {appDetails?.status === "approved"
                                ? "Accepted"
                                : appDetails?.status === "rejected"
                                ? "Rejected"
                                : "Pending"}
                            </span>
                          ) : p.status !== "open" ? (
                            <span className="text-xs text-muted font-bold">Closed</span>
                          ) : (p.slots_left !== undefined ? p.slots_left : p.slots) <= 0 ? (
                            <span className="text-xs text-error font-bold">Slots Full</span>
                          ) : (
                            <span className="text-xs font-bold text-emerald group-hover:underline">
                              Apply Now →
                            </span>
                          )}
                        </div>
                      </div>
                    </div>
                  );
                })
              ) : (
                <div className="col-span-full py-16 text-center text-sm text-muted">
                  No volunteer programs match your filters.
                </div>
              )}
            </div>
          )}
        </div>
      ) : (
        /* ================== CALENDAR VIEW ================== */
        <Card>
          {/* Calendar Header Controls */}
          <div className="flex items-center justify-between border-b border-sand-dark/60 px-5 py-4 bg-sand/20">
            <h2 className="text-sm font-extrabold text-ink flex items-center gap-2">
              <CalendarIcon size={16} className="text-emerald" />
              {currentDate.toLocaleDateString("en-MY", { month: "long", year: "numeric" })}
            </h2>
            <div className="flex gap-1">
              <button
                onClick={() => changeMonth(-1)}
                className="rounded-card border border-sand-dark bg-white p-2 text-muted hover:text-ink shadow-sm"
              >
                <ChevronLeft size={16} />
              </button>
              <button
                onClick={() => changeMonth(1)}
                className="rounded-card border border-sand-dark bg-white p-2 text-muted hover:text-ink shadow-sm"
              >
                <ChevronRight size={16} />
              </button>
            </div>
          </div>

          {/* Calendar Grid */}
          <div className="grid grid-cols-7 border-b border-sand-dark/40 bg-sand/10 text-center text-[10px] font-bold text-muted uppercase tracking-wider py-2">
            <div>Sun</div>
            <div>Mon</div>
            <div>Tue</div>
            <div>Wed</div>
            <div>Thu</div>
            <div>Fri</div>
            <div>Sat</div>
          </div>

          <div className="grid grid-cols-7 bg-white divide-x divide-y divide-sand-dark/30 border-t border-sand-dark/30">
            {calendarDays.map((day, idx) => {
              if (!day) return <div key={`empty-${idx}`} className="h-28 bg-sand/15" />;

              const dayString = day.toDateString();
              // Find all programs on this specific day
              const dayPrograms = programs.filter(
                (p) => new Date(p.start_at).toDateString() === dayString
              );

              const isToday = new Date().toDateString() === dayString;

              return (
                <div
                  key={dayString}
                  className={`h-28 p-1.5 flex flex-col justify-between transition-colors ${
                    isToday ? "bg-emerald-light/20" : "hover:bg-sand/10"
                  }`}
                >
                  <span
                    className={`inline-flex h-5 w-5 items-center justify-center text-xs font-bold rounded-full self-end ${
                      isToday ? "bg-emerald text-white" : "text-muted"
                    }`}
                  >
                    {day.getDate()}
                  </span>
                  <div className="flex-1 overflow-y-auto space-y-1 mt-1 scrollbar-thin">
                    {dayPrograms.map((p) => (
                      <button
                        key={p.id}
                        onClick={() => {
                          setSelectedProgram(p);
                          setDetailsOpen(true);
                        }}
                        className={`w-full text-left rounded px-1.5 py-0.5 text-[9px] font-bold truncate block border transition-colors ${
                          p.status === "completed"
                            ? "bg-sand border-sand-dark text-muted"
                            : "bg-emerald-light border-emerald/20 text-emerald hover:bg-emerald hover:text-white"
                        }`}
                        title={p.title}
                      >
                        {p.title}
                      </button>
                    ))}
                  </div>
                </div>
              );
            })}
          </div>
        </Card>
      )}

      {/* CREATE/EDIT MODAL (ADMIN ONLY) */}
      {userRole === "admin" && (
        <Modal open={open} onClose={() => setOpen(false)} title={form.id ? "Edit program" : "Create program"} wide>
          <form onSubmit={save} className="space-y-4">
            <Field label="Title">
              <Input
                required
                value={form.title}
                onChange={(e) => setForm({ ...form, title: e.target.value })}
                placeholder="Gotong-Royong Masjid"
              />
            </Field>
            <Field label="Description">
              <Textarea
                required
                rows={3}
                value={form.description}
                onChange={(e) => setForm({ ...form, description: e.target.value })}
                placeholder="Open to all students — no prior experience required."
              />
            </Field>
            <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
              <Field label="Venue">
                <Input
                  value={form.venue}
                  onChange={(e) => setForm({ ...form, venue: e.target.value })}
                  placeholder="Masjid Sultan Idris, UPSI"
                />
              </Field>
              <Field label="Status">
                <Select value={form.status} onChange={(e) => setForm({ ...form, status: e.target.value as Program["status"] })}>
                  <option value="open">Open</option>
                  <option value="closed">Closed</option>
                  <option value="completed">Completed</option>
                </Select>
              </Field>
              <Field label="Starts">
                <Input
                  type="datetime-local"
                  required
                  value={form.start_at}
                  onChange={(e) => setForm({ ...form, start_at: e.target.value })}
                />
              </Field>
              <Field label="Ends (optional)">
                <Input
                  type="datetime-local"
                  value={form.end_at}
                  onChange={(e) => setForm({ ...form, end_at: e.target.value })}
                />
              </Field>
              <Field label="Slots">
                <Input
                  type="number"
                  min={0}
                  required
                  value={form.slots}
                  onChange={(e) => setForm({ ...form, slots: Number(e.target.value) })}
                />
              </Field>
              <Field label="Merit points">
                <Input
                  type="number"
                  min={0}
                  required
                  value={form.merit_value}
                  onChange={(e) => setForm({ ...form, merit_value: Number(e.target.value) })}
                />
              </Field>
              <div className="sm:col-span-2 space-y-3">
                <Field label="Choose Preset Asset Photo" hint="Select a ready-made illustration from the assets folder.">
                  <div className="grid grid-cols-4 gap-2 bg-sand/30 p-2.5 rounded-card border border-sand-dark/60">
                    {[
                      "/assets/masjid_cleanup.png",
                      "/assets/quran_study.png",
                      "/assets/food_charity.png",
                      "/assets/media_crew.png"
                    ].map((assetPath) => (
                      <button
                        key={assetPath}
                        type="button"
                        onClick={() => setForm({ ...form, image_url: assetPath })}
                        className={`relative p-1 rounded-card border hover:border-emerald transition-colors ${
                          form.image_url === assetPath ? "border-emerald bg-emerald-light/20" : "border-sand-dark/60 bg-white"
                        }`}
                      >
                        <img src={assetPath} alt="Asset" className="h-12 w-full object-cover rounded" />
                      </button>
                    ))}
                  </div>
                </Field>

                <Field label="Or Upload Custom Photo" hint="Attach or drag-and-drop a photo. Stored as local Base64.">
                  <div className="mt-1 flex flex-col items-center justify-center rounded-card border-2 border-dashed border-sand-dark/60 bg-white p-5 hover:border-emerald/50 transition-colors relative min-h-36">
                    {form.image_url && !form.image_url.startsWith("/assets/") ? (
                      <div className="relative w-full max-h-48 overflow-hidden rounded-card">
                        <img
                          src={form.image_url}
                          alt="Program Preview"
                          className="w-full h-40 object-cover rounded-card"
                        />
                        <button
                          type="button"
                          onClick={() => setForm({ ...form, image_url: "" })}
                          className="absolute top-2 right-2 rounded-full bg-black/60 px-3 py-1 text-white hover:bg-black transition-colors text-xs font-bold"
                        >
                          Remove Photo
                        </button>
                      </div>
                    ) : (
                      <div className="text-center py-2">
                        <div className="mx-auto flex h-10 w-10 items-center justify-center rounded-full bg-emerald-light text-emerald mb-2">
                          <ImageIcon size={20} />
                        </div>
                        <p className="text-xs text-ink font-semibold">
                          Drag & drop image here, or{" "}
                          <label className="text-emerald cursor-pointer hover:underline font-bold">
                            browse
                            <input
                              type="file"
                              accept="image/*"
                              className="hidden"
                              onChange={(e) => {
                                const file = e.target.files?.[0];
                                if (!file) return;
                                const reader = new FileReader();
                                reader.onload = (ue) => {
                                  setForm({ ...form, image_url: ue.target?.result as string });
                                };
                                reader.readAsDataURL(file);
                              }}
                            />
                          </label>
                        </p>
                        <p className="text-[10px] text-muted mt-1">PNG, JPG, GIF up to 5MB</p>
                      </div>
                    )}

                    {/* Drag over cover element */}
                    {(!form.image_url || form.image_url.startsWith("/assets/")) && (
                      <div
                        className="absolute inset-0 opacity-0 cursor-pointer"
                        onDragOver={(e) => e.preventDefault()}
                        onDrop={(e) => {
                          e.preventDefault();
                          const file = e.dataTransfer.files?.[0];
                          if (file && file.type.startsWith("image/")) {
                            const reader = new FileReader();
                            reader.onload = (ue) => {
                              setForm({ ...form, image_url: ue.target?.result as string });
                            };
                            reader.readAsDataURL(file);
                          }
                        }}
                      />
                    )}
                  </div>
                </Field>
              </div>
            </div>
            <Field label="Required skills" hint="Used for skill-based recommendations.">
              <Chips
                options={skills}
                selected={selectedSkills}
                onToggle={toggleSkill}
              />
            </Field>
            <div className="flex justify-end gap-2 pt-2">
              <Button type="button" variant="secondary" onClick={() => setOpen(false)}>
                Cancel
              </Button>
              <Button type="submit" disabled={saving}>
                {saving ? "Saving…" : form.id ? "Save changes" : "Create program"}
              </Button>
            </div>
          </form>
        </Modal>
      )}

      {/* STUDENT DETAILS & DYNAMIC GOOGLE CALENDAR MODAL */}
      {selectedProgram && (
        <Modal
          open={detailsOpen}
          onClose={() => setDetailsOpen(false)}
          title={selectedProgram.title}
          wide
        >
          <div className="space-y-4">
            <div className="flex flex-col md:flex-row gap-4">
              {/* Left Column: Image */}
              {selectedProgram.image_url && (
                <div className="md:w-1/3">
                  <img
                    src={selectedProgram.image_url}
                    alt={selectedProgram.title}
                    className="w-full h-40 object-cover rounded-card border border-sand-dark"
                  />
                </div>
              )}
              {/* Right Column: Description */}
              <div className="flex-1">
                <p className="text-xs text-muted uppercase tracking-wide font-semibold">Description</p>
                <p className="mt-1 text-sm text-ink leading-relaxed whitespace-pre-wrap">
                  {selectedProgram.description}
                </p>
              </div>
            </div>

            <div className="grid grid-cols-2 gap-4">
              <div>
                <p className="text-xs text-muted uppercase tracking-wide font-semibold">Venue</p>
                <p className="mt-0.5 text-sm font-semibold text-ink">📍 {selectedProgram.venue ?? "Online"}</p>
              </div>
              <div>
                <p className="text-xs text-muted uppercase tracking-wide font-semibold">Merit Value</p>
                <p className="mt-0.5 text-sm font-semibold text-emerald">🎖️ {selectedProgram.merit_value} Merit Points</p>
              </div>
              <div>
                <p className="text-xs text-muted uppercase tracking-wide font-semibold">Starts At</p>
                <p className="mt-0.5 text-sm text-ink font-medium">📅 {formatDate(selectedProgram.start_at)}</p>
              </div>
              <div>
                <p className="text-xs text-muted uppercase tracking-wide font-semibold">Slots Available</p>
                <p className="mt-0.5 text-sm text-ink font-semibold">
                  {selectedProgram.slots_left !== undefined ? `${selectedProgram.slots_left} / ${selectedProgram.slots}` : `${selectedProgram.slots} slots`}
                </p>
              </div>
            </div>

            {/* Skills chip list */}
            <div>
              <p className="text-xs text-muted uppercase tracking-wide font-semibold mb-1.5">Required Skills</p>
              <div className="flex flex-wrap gap-1.5">
                {(selectedProgram.program_skills ?? []).length > 0 ? (
                  (selectedProgram.program_skills ?? []).map((ps: any) => {
                    const hasSkill = studentSkills.includes(ps.skills?.name);
                    return (
                      <span
                        key={ps.skills?.id}
                        className={`rounded-full px-2.5 py-1 text-xs font-medium border ${
                          hasSkill
                            ? "bg-emerald-light border-emerald text-emerald font-bold"
                            : "bg-sand border-sand-dark text-muted"
                        }`}
                      >
                        {ps.skills?.name} {hasSkill && "✓"}
                      </span>
                    );
                  })
                ) : (
                  <span className="text-xs text-muted">—</span>
                )}
              </div>
            </div>

            {/* Actions */}
            <div className="flex justify-between items-center pt-4 border-t border-sand-dark/30">
              {/* Add to Google Calendar button */}
              <a
                href={getGoogleCalendarUrl(selectedProgram)}
                target="_blank"
                rel="noopener noreferrer"
                className="inline-flex items-center gap-1 text-xs font-bold text-emerald hover:underline"
              >
                <ExternalLink size={14} /> Add to Google Calendar
              </a>

              <div className="flex gap-2">
                <Button variant="secondary" onClick={() => setDetailsOpen(false)}>
                  Close
                </Button>
                {userRole === "volunteer" && (
                  applications.some((a) => a.program_id === selectedProgram.id) ? (
                    <Button disabled variant="primary">
                      Already Applied
                    </Button>
                  ) : selectedProgram.status !== "open" ? (
                    <Button disabled variant="primary">
                      Program Closed
                    </Button>
                  ) : (selectedProgram.slots_left !== undefined ? selectedProgram.slots_left : selectedProgram.slots) <= 0 ? (
                    <Button disabled variant="primary">
                      Slots Full
                    </Button>
                  ) : (
                    <Button onClick={() => applyToProgram(selectedProgram.id)} variant="primary">
                      Apply for Program
                    </Button>
                  )
                )}
              </div>
            </div>
          </div>
        </Modal>
      )}

      {/* ATTENDANCE QR MODAL (ADMIN ONLY) */}
      <QrCheckinModal program={qrProgram} onClose={() => setQrProgram(null)} />

      {/* ATTENDANCE VIEW + EXPORT MODAL (ADMIN ONLY) */}
      <Modal
        open={!!attendanceProgram}
        onClose={() => {
          setAttendanceProgram(null);
          setAttendanceSearch("");
        }}
        title={attendanceProgram ? `Attendance — ${attendanceProgram.title}` : "Attendance"}
        wide
      >
        {attendanceProgram && (
          <div className="space-y-4">
            <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
              <div className="relative flex-1 max-w-sm">
                <Search size={15} className="absolute left-3 top-1/2 -translate-y-1/2 text-muted" />
                <Input
                  className="pl-9 text-sm"
                  placeholder="Search by name, matric no., email..."
                  value={attendanceSearch}
                  onChange={(e) => setAttendanceSearch(e.target.value)}
                />
              </div>
              <div className="flex gap-2">
                <Button
                  variant="secondary"
                  onClick={exportAttendancePdf}
                  disabled={attendanceLoading || !filteredAttendanceRows.length}
                >
                  <FileDown size={15} /> Export PDF
                </Button>
                <Button
                  variant="secondary"
                  onClick={exportAttendanceExcel}
                  disabled={attendanceLoading || !filteredAttendanceRows.length}
                >
                  <FileSpreadsheet size={15} /> Export Excel
                </Button>
              </div>
            </div>

            <Card>
              <Table headers={["#", "Full Name", "Matric No.", "Email", "Checked In At"]}>
                {attendanceLoading ? (
                  <tr>
                    <td colSpan={5} className="py-10">
                      <Spinner label="Loading attendance…" />
                    </td>
                  </tr>
                ) : filteredAttendanceRows.length ? (
                  filteredAttendanceRows.map((r, i) => (
                    <tr key={r.volunteer_id} className="hover:bg-sand/40">
                      <Td className="text-muted">{i + 1}</Td>
                      <Td className="font-semibold">{r.full_name}</Td>
                      <Td>{r.matric_no ?? "—"}</Td>
                      <Td className="text-muted">{r.email ?? "—"}</Td>
                      <Td className="text-muted">{formatDateTime(r.checked_in_at)}</Td>
                    </tr>
                  ))
                ) : (
                  <EmptyRow colSpan={5} message="No attendance records for this program yet." />
                )}
              </Table>
            </Card>

            <div className="flex items-center justify-between text-xs text-muted">
              <span className="flex items-center gap-1.5">
                <Users size={13} /> {filteredAttendanceRows.length} of {attendanceRows.length} shown
              </span>
              <Button variant="secondary" onClick={() => setAttendanceProgram(null)}>
                Close
              </Button>
            </div>
          </div>
        )}
      </Modal>
    </div>
  );
}