import { useEffect, useMemo, useState } from "react";
import { useQuery } from "@tanstack/react-query";
import {
  CalendarClock,
  CheckCircle2,
  Loader2,
  AlertTriangle,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { DateTimePicker } from "@/components/date-time-picker";
import {
  AttendeeTableEditor,
  emptyAttendeeRow,
  syncAttendeeRows,
  type EditableAttendeeRow,
} from "@/components/attendee-table-editor";

const API = `${import.meta.env.BASE_URL}api`;

type PublicRoom = { id: number; nameAr: string; nameEn: string };

// Availability for one room + Riyadh calendar day: the admin-configured slot
// grid with per-slot booked / too-soon flags. An empty `slots` array means
// the admin hasn't configured slots — the form falls back to free date-time
// pickers (legacy mode).
type AvailabilitySlot = {
  id: number;
  startTime: string; // "HH:mm" Riyadh wall clock
  durationMinutes: number;
  booked: boolean;
  tooSoon: boolean;
  available: boolean;
};
type Availability = { minLeadMinutes: number; slots: AvailabilitySlot[] };

function fmtSlotLabel(startTime: string, durationMinutes: number): string {
  const [h, m] = startTime.split(":").map(Number);
  const endTotal = h * 60 + m + durationMinutes;
  const eh = Math.floor(endTotal / 60) % 24;
  const em = endTotal % 60;
  const pad = (n: number) => String(n).padStart(2, "0");
  const to12 = (hh: number, mm: number) => {
    const period = hh < 12 ? "ص" : "م";
    let h12 = hh % 12;
    if (h12 === 0) h12 = 12;
    return `${h12}:${pad(mm)} ${period}`;
  };
  return `${to12(h, m)} – ${to12(eh, em)}`;
}

// Slot start/end as absolute instants. Riyadh has no DST so the fixed
// +03:00 offset is always correct.
function slotIso(date: string, startTime: string, durationMinutes?: number) {
  const start = new Date(`${date}T${startTime}:00+03:00`);
  if (durationMinutes === undefined) return start.toISOString();
  return new Date(start.getTime() + durationMinutes * 60_000).toISOString();
}

function todayRiyadh(): string {
  // en-CA gives YYYY-MM-DD directly.
  return new Intl.DateTimeFormat("en-CA", {
    timeZone: "Asia/Riyadh",
  }).format(new Date());
}

type MeetingType = "internal" | "external";

type FormState = {
  requesterName: string;
  title: string;
  requesterPhone: string;
  department: string;
  meetingType: MeetingType;
  requesterOrg: string;
  attendeeCount: string;
  purpose: string;
  roomId: string;
  date: string; // YYYY-MM-DD (Riyadh calendar day) — slot mode
  slotId: string; // selected slot id — slot mode
  startsAt: string; // legacy free mode (no slots configured)
  endsAt: string;
  notes: string;
  website: string; // honeypot
};

const EMPTY: FormState = {
  requesterName: "",
  title: "",
  requesterPhone: "",
  department: "",
  meetingType: "internal",
  requesterOrg: "",
  attendeeCount: "",
  purpose: "",
  roomId: "",
  date: "",
  slotId: "",
  startsAt: "",
  endsAt: "",
  notes: "",
  website: "",
};

function localToIso(v: string): string {
  return new Date(v).toISOString();
}

export default function ProtocolRequestPage() {
  // This page is public (no auth). Force RTL Arabic regardless of any
  // stored language preference so a guest always sees the intended form.
  useEffect(() => {
    const prevDir = document.documentElement.dir;
    const prevLang = document.documentElement.lang;
    document.documentElement.dir = "rtl";
    document.documentElement.lang = "ar";
    return () => {
      // Restore the app's direction/language so navigating away from this
      // public page doesn't leave the rest of the app forced into RTL Arabic.
      document.documentElement.dir = prevDir;
      document.documentElement.lang = prevLang;
    };
  }, []);

  const rooms = useQuery<PublicRoom[]>({
    queryKey: ["protocol-public", "rooms"],
    queryFn: async () => {
      const r = await fetch(`${API}/protocol/public/rooms`);
      if (!r.ok) throw new Error("rooms");
      return r.json();
    },
  });

  const [form, setForm] = useState<FormState>(EMPTY);

  // Availability (slot grid) for the chosen room + day. When the admin has
  // configured slots, guests pick a day then one of the returned slots; the
  // legacy free start/end pickers only render when no slots exist at all.
  const availability = useQuery<Availability>({
    queryKey: ["protocol-public", "availability", form.roomId, form.date],
    enabled: form.roomId !== "" && form.date !== "",
    queryFn: async () => {
      const r = await fetch(
        `${API}/protocol/public/availability?roomId=${encodeURIComponent(
          form.roomId,
        )}&date=${encodeURIComponent(form.date)}`,
      );
      if (!r.ok) throw new Error("availability");
      return r.json();
    },
  });
  // Probe with today's date before a day is picked, so we know whether slot
  // mode is on (the slot list itself is per-day, but its existence is global).
  const slotProbe = useQuery<Availability>({
    queryKey: ["protocol-public", "availability-probe", form.roomId],
    enabled: form.roomId !== "",
    queryFn: async () => {
      const r = await fetch(
        `${API}/protocol/public/availability?roomId=${encodeURIComponent(
          form.roomId,
        )}&date=${todayRiyadh()}`,
      );
      if (!r.ok) throw new Error("availability");
      return r.json();
    },
  });
  const slotMode =
    form.roomId !== "" &&
    slotProbe.data !== undefined &&
    slotProbe.data.slots.length > 0;
  const daySlots = availability.data?.slots ?? [];
  const selectedSlot = daySlots.find((s) => String(s.id) === form.slotId);
  // Key attendees ("أبرز الحضور"): one numbered table where each row carries
  // its own side (من الهيئة / خارج الهيئة). Row count follows the expected
  // attendee count field.
  const [attendees, setAttendees] = useState<EditableAttendeeRow[]>([
    emptyAttendeeRow(),
  ]);
  const [submitting, setSubmitting] = useState(false);
  const [done, setDone] = useState(false);
  const [reference, setReference] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  const set = <K extends keyof FormState>(k: K, v: FormState[K]) =>
    setForm((f) => ({ ...f, [k]: v }));

  // Auto-generate table rows to match "العدد المتوقع للحضور".
  useEffect(() => {
    const n =
      form.attendeeCount.trim() === "" ? null : Number(form.attendeeCount);
    setAttendees((rs) => syncAttendeeRows(rs, n));
  }, [form.attendeeCount]);

  const isExternal = form.meetingType === "external";

  const canSubmit = useMemo(() => {
    const timeOk = slotMode
      ? form.date !== "" && selectedSlot !== undefined && selectedSlot.available
      : form.startsAt !== "" &&
        form.endsAt !== "" &&
        new Date(form.startsAt) < new Date(form.endsAt);
    return (
      form.requesterName.trim().length > 0 &&
      form.title.trim().length > 0 &&
      form.requesterPhone.trim().length >= 3 &&
      form.roomId !== "" &&
      timeOk &&
      (!isExternal || form.requesterOrg.trim().length > 0)
    );
  }, [form, isExternal, slotMode, selectedSlot]);

  const onSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setError(null);
    if (!canSubmit || submitting) return;
    setSubmitting(true);
    try {
      const keyAttendees = attendees
        .filter((r) => r.name.trim() !== "")
        .map((r) => ({
          name: r.name.trim(),
          position: r.position.trim(),
          side: r.side,
        }));
      const res = await fetch(`${API}/protocol/public/booking-requests`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          roomId: Number(form.roomId),
          title: form.title.trim(),
          requesterName: form.requesterName.trim(),
          requesterPhone: form.requesterPhone.trim(),
          department: form.department.trim() || null,
          meetingType: form.meetingType,
          requesterOrg: isExternal ? form.requesterOrg.trim() : null,
          purpose: form.purpose.trim() || null,
          attendeeCount:
            form.attendeeCount.trim() === ""
              ? null
              : Number(form.attendeeCount),
          keyAttendees,
          startsAt:
            slotMode && selectedSlot
              ? slotIso(form.date, selectedSlot.startTime)
              : localToIso(form.startsAt),
          endsAt:
            slotMode && selectedSlot
              ? slotIso(
                  form.date,
                  selectedSlot.startTime,
                  selectedSlot.durationMinutes,
                )
              : localToIso(form.endsAt),
          notes: form.notes.trim() || null,
          website: form.website,
        }),
      });
      if (res.ok) {
        try {
          const data = await res.json();
          if (data?.bookingReference && typeof data.bookingReference === "string") {
            setReference(data.bookingReference);
          }
        } catch {
          // no reference in body — still a success
        }
        setDone(true);
        return;
      }
      let msg = "تعذّر إرسال الطلب، يرجى المحاولة مرة أخرى.";
      try {
        const data = await res.json();
        if (data?.error && typeof data.error === "string") msg = data.error;
      } catch {
        // keep default message
      }
      if (res.status === 429) {
        msg = "لقد أرسلت طلبات كثيرة، يرجى المحاولة لاحقاً.";
      }
      setError(msg);
    } catch {
      setError("تعذّر الاتصال بالخادم، تحقق من الاتصال وحاول مجدداً.");
    } finally {
      setSubmitting(false);
    }
  };

  const resetForm = () => {
    setForm(EMPTY);
    setAttendees([emptyAttendeeRow()]);
    setReference(null);
    setDone(false);
  };

  if (done) {
    return (
      <div
        dir="rtl"
        className="min-h-screen bg-slate-50 flex items-center justify-center p-4"
      >
        <div className="w-full max-w-md bg-white rounded-2xl border border-slate-200 shadow-sm p-8 text-center">
          <CheckCircle2 className="w-14 h-14 text-emerald-500 mx-auto mb-4" />
          <h1 className="text-xl font-bold text-slate-800 mb-2">
            تم استلام طلبك
          </h1>
          <p className="text-slate-500 leading-relaxed">
            سيقوم فريق المراسم بمراجعة طلب الحجز والتواصل معك على رقم الهاتف
            المُدخل لتأكيد الموعد.
          </p>
          {reference && (
            <div className="mt-5 rounded-xl bg-sky-50 border border-sky-200 px-4 py-4">
              <p className="text-sm text-slate-500 mb-1">رقم الحجز</p>
              <p
                className="text-2xl font-bold tracking-wider text-sky-700"
                dir="ltr"
              >
                {reference}
              </p>
              <p className="text-xs text-slate-500 mt-2">
                احتفظ بهذا الرقم لمتابعة حالة طلبك.
              </p>
            </div>
          )}
          <Button className="mt-6" variant="outline" onClick={resetForm}>
            إرسال طلب آخر
          </Button>
        </div>
      </div>
    );
  }

  return (
    <div dir="rtl" className="min-h-screen bg-slate-50 py-8 px-4">
      <div className="w-full max-w-xl mx-auto">
        <div className="flex items-center gap-3 mb-6">
          <div className="w-11 h-11 rounded-xl bg-sky-500/10 text-sky-600 flex items-center justify-center">
            <CalendarClock className="w-6 h-6" />
          </div>
          <div>
            <h1 className="text-xl font-bold text-slate-800">طلب حجز قاعة</h1>
            <p className="text-sm text-slate-500">
              يرجى تعبئة البيانات وسيتواصل معك فريق المراسم للتأكيد.
            </p>
          </div>
        </div>

        <form
          onSubmit={onSubmit}
          className="bg-white rounded-2xl border border-slate-200 shadow-sm p-6 space-y-5"
        >
          {/* Honeypot: hidden from real users, catches bots. */}
          <div className="hidden" aria-hidden="true">
            <label>
              Website
              <input
                type="text"
                tabIndex={-1}
                autoComplete="off"
                value={form.website}
                onChange={(e) => set("website", e.target.value)}
              />
            </label>
          </div>

          <div className="space-y-2">
            <Label htmlFor="requesterName">
              الاسم <span className="text-rose-500">*</span>
            </Label>
            <Input
              id="requesterName"
              value={form.requesterName}
              onChange={(e) => set("requesterName", e.target.value)}
              placeholder="الاسم الثلاثي"
              required
            />
          </div>

          <div className="space-y-2">
            <Label htmlFor="requesterPhone">
              رقم الهاتف للتواصل <span className="text-rose-500">*</span>
            </Label>
            <Input
              id="requesterPhone"
              type="tel"
              inputMode="tel"
              dir="ltr"
              className="text-right"
              value={form.requesterPhone}
              onChange={(e) => set("requesterPhone", e.target.value)}
              placeholder="05xxxxxxxx"
              required
            />
          </div>

          <div className="space-y-2">
            <Label htmlFor="room">
              القاعة <span className="text-rose-500">*</span>
            </Label>
            <Select
              value={form.roomId}
              onValueChange={(v) =>
                // Reset the time selection when the room changes so no stale
                // date/slot/free-time values survive a room switch (the slot
                // grid is per-room and slot mode itself may flip).
                setForm((f) => ({
                  ...f,
                  roomId: v,
                  date: "",
                  slotId: "",
                  startsAt: "",
                  endsAt: "",
                }))
              }
            >
              <SelectTrigger id="room">
                <SelectValue
                  placeholder={
                    rooms.isLoading ? "جارٍ التحميل…" : "اختر القاعة"
                  }
                />
              </SelectTrigger>
              <SelectContent>
                {(rooms.data ?? []).map((r) => (
                  <SelectItem key={r.id} value={String(r.id)}>
                    {r.nameAr || r.nameEn}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
            {rooms.isError && (
              <p className="text-xs text-rose-500">
                تعذّر تحميل قائمة القاعات، يرجى تحديث الصفحة.
              </p>
            )}
          </div>

          <div className="space-y-2">
            <Label htmlFor="department">الإدارة</Label>
            <Input
              id="department"
              value={form.department}
              onChange={(e) => set("department", e.target.value)}
              placeholder="الإدارة أو القسم (اختياري)"
            />
          </div>

          <div className="space-y-2">
            <Label htmlFor="title">
              عنوان الاجتماع <span className="text-rose-500">*</span>
            </Label>
            <Input
              id="title"
              value={form.title}
              onChange={(e) => set("title", e.target.value)}
              placeholder="موضوع أو عنوان الاجتماع"
              required
            />
          </div>

          <div className="space-y-2">
            <Label>
              نوع الاجتماع <span className="text-rose-500">*</span>
            </Label>
            <div className="grid grid-cols-2 gap-2">
              {(
                [
                  { value: "internal", label: "اجتماع داخلي" },
                  { value: "external", label: "اجتماع مع جهة خارجية" },
                ] as const
              ).map((opt) => (
                <button
                  key={opt.value}
                  type="button"
                  onClick={() => set("meetingType", opt.value)}
                  className={`rounded-lg border px-3 py-2.5 text-sm font-medium transition-colors ${
                    form.meetingType === opt.value
                      ? "border-sky-500 bg-sky-50 text-sky-700"
                      : "border-slate-200 bg-white text-slate-600 hover:border-slate-300"
                  }`}
                >
                  {opt.label}
                </button>
              ))}
            </div>
          </div>

          {isExternal && (
            <div className="space-y-2">
              <Label htmlFor="requesterOrg">
                اسم الجهة <span className="text-rose-500">*</span>
              </Label>
              <Input
                id="requesterOrg"
                value={form.requesterOrg}
                onChange={(e) => set("requesterOrg", e.target.value)}
                placeholder="اسم الجهة الخارجية"
                required
              />
            </div>
          )}

          <div className="space-y-2">
            <Label htmlFor="attendeeCount">العدد المتوقع للحضور</Label>
            <Input
              id="attendeeCount"
              type="number"
              inputMode="numeric"
              min={1}
              value={form.attendeeCount}
              onChange={(e) => set("attendeeCount", e.target.value)}
              placeholder="العدد المتوقع للحضور (اختياري)"
            />
          </div>

          <div className="space-y-2">
            <Label htmlFor="purpose">الغرض من الاجتماع</Label>
            <Textarea
              id="purpose"
              value={form.purpose}
              onChange={(e) => set("purpose", e.target.value)}
              placeholder="اشرح الغرض من الاجتماع (اختياري)"
              rows={2}
            />
          </div>

          {form.roomId === "" ? (
            // No room chosen yet → we don't know whether slot mode is on, so
            // show a hint instead of the (possibly wrong) free pickers.
            <div className="space-y-2">
              <Label>
                موعد الحجز <span className="text-rose-500">*</span>
              </Label>
              <p className="rounded-lg border border-slate-200 bg-slate-50 px-3 py-3 text-sm text-slate-500">
                اختر القاعة أولًا لعرض المواعيد المتاحة.
              </p>
            </div>
          ) : slotProbe.isLoading ? (
            <div className="space-y-2">
              <Label>
                موعد الحجز <span className="text-rose-500">*</span>
              </Label>
              <p className="text-sm text-slate-500">
                جارٍ تحميل المواعيد المتاحة…
              </p>
            </div>
          ) : slotProbe.isError ? (
            <div className="space-y-2">
              <Label>
                موعد الحجز <span className="text-rose-500">*</span>
              </Label>
              <p className="text-xs text-rose-500">
                تعذّر تحميل المواعيد، يرجى المحاولة مرة أخرى.
              </p>
            </div>
          ) : slotMode ? (
            <>
              <div className="space-y-2">
                <Label htmlFor="bookingDate">
                  تاريخ الحجز <span className="text-rose-500">*</span>
                </Label>
                <Input
                  id="bookingDate"
                  type="date"
                  min={todayRiyadh()}
                  value={form.date}
                  onChange={(e) => {
                    set("date", e.target.value);
                    set("slotId", "");
                  }}
                />
              </div>
              {form.date !== "" && (
                <div className="space-y-2">
                  <Label>
                    الوقت المتاح <span className="text-rose-500">*</span>
                  </Label>
                  {availability.isLoading && (
                    <p className="text-sm text-slate-500">
                      جارٍ تحميل الأوقات المتاحة…
                    </p>
                  )}
                  {availability.isError && (
                    <p className="text-xs text-rose-500">
                      تعذّر تحميل الأوقات، يرجى المحاولة مرة أخرى.
                    </p>
                  )}
                  {availability.data && (
                    <>
                      <div className="grid grid-cols-2 gap-2">
                        {daySlots.map((s) => (
                          <button
                            key={s.id}
                            type="button"
                            disabled={!s.available}
                            onClick={() => set("slotId", String(s.id))}
                            className={`rounded-lg border px-3 py-2.5 text-sm font-medium transition-colors ${
                              form.slotId === String(s.id)
                                ? "border-sky-500 bg-sky-50 text-sky-700"
                                : s.available
                                  ? "border-slate-200 bg-white text-slate-600 hover:border-slate-300"
                                  : "border-slate-100 bg-slate-50 text-slate-300 cursor-not-allowed line-through"
                            }`}
                            dir="rtl"
                          >
                            {fmtSlotLabel(s.startTime, s.durationMinutes)}
                          </button>
                        ))}
                      </div>
                      {daySlots.length > 0 &&
                        daySlots.every((s) => !s.available) && (
                          <p className="text-xs text-amber-600">
                            لا توجد أوقات متاحة في هذا اليوم، يرجى اختيار يوم
                            آخر.
                          </p>
                        )}
                    </>
                  )}
                </div>
              )}
            </>
          ) : (
            <>
              <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
                <div className="space-y-2">
                  <Label htmlFor="startsAt">
                    من <span className="text-rose-500">*</span>
                  </Label>
                  <DateTimePicker
                    id="startsAt"
                    value={form.startsAt}
                    onChange={(v) => set("startsAt", v)}
                    placeholder="اختر تاريخ ووقت البداية"
                  />
                </div>
                <div className="space-y-2">
                  <Label htmlFor="endsAt">
                    إلى <span className="text-rose-500">*</span>
                  </Label>
                  <DateTimePicker
                    id="endsAt"
                    value={form.endsAt}
                    onChange={(v) => set("endsAt", v)}
                    placeholder="اختر تاريخ ووقت النهاية"
                    minDate={form.startsAt ? new Date(form.startsAt) : undefined}
                  />
                </div>
              </div>
              {form.startsAt !== "" &&
                form.endsAt !== "" &&
                new Date(form.startsAt) >= new Date(form.endsAt) && (
                  <p className="text-xs text-rose-500 -mt-2">
                    يجب أن يكون وقت البداية قبل وقت النهاية.
                  </p>
                )}
            </>
          )}

          <div className="space-y-3">
            <Label>أبرز الحضور</Label>
            <AttendeeTableEditor
              rows={attendees}
              setRows={setAttendees}
              labels={{
                name: "الاسم",
                position: "المنصب",
                side: "الجهة",
                sideInternal: "من الهيئة",
                sideExternal: "خارج الهيئة",
                addRow: "إضافة صف",
                removeRow: "حذف الصف",
              }}
            />
          </div>

          <div className="space-y-2">
            <Label htmlFor="notes">ملاحظات</Label>
            <Textarea
              id="notes"
              value={form.notes}
              onChange={(e) => set("notes", e.target.value)}
              placeholder="أي تفاصيل إضافية (اختياري)"
              rows={3}
            />
          </div>

          <div className="flex items-start gap-2 rounded-lg bg-rose-50 border border-rose-200 text-rose-700 text-sm px-3 py-3">
            <AlertTriangle className="w-4 h-4 mt-0.5 shrink-0" />
            <span>
              للإحاطة: في حال الحاجة للقاعة سيتم إلغاء الاجتماع أو تعديل موقعه.
            </span>
          </div>

          {error && (
            <div className="rounded-lg bg-rose-50 border border-rose-200 text-rose-700 text-sm px-3 py-2">
              {error}
            </div>
          )}

          <Button
            type="submit"
            className="w-full"
            disabled={!canSubmit || submitting}
          >
            {submitting && <Loader2 className="w-4 h-4 animate-spin" />}
            إرسال الطلب
          </Button>
        </form>
      </div>
    </div>
  );
}
