import { useEffect, useMemo, useState } from "react";
import { ChevronLeft, ChevronRight, Phone, X, Calendar as CalendarIcon } from "lucide-react";
import { fetchRdbmsLookupRecords } from "../../api/viewService";
import { CALENDAR_LOOKUPS, WORKFLOW_NUMERIC_ID, ACTIVITY_IDS } from "../../config";

const ACCENT      = "#e31837";
const ACCENT_SOFT = "#fde2e8";
const TM_NAVY     = "#061f5c";
const TM_BORDER   = "#e4e4ed";
const INK         = "#17181a";
const IST_OFFSET_MIN = 330;

interface TestDrive {
  id: number;
  dealer_id: number;
  car_id: number;
  slot_start: string;
  slot_end: string;
  status: "available" | "booked";
  customer_name?: string | null;
  customer_phone?: string | null;
  booked_at?: string | null;
  completed_at?: string | null;
  feedback_rating?: number | null;
  feedback_liked_most?: string | null;
  feedback_concern?: string | null;
  feedback_would_recommend?: boolean | null;
  feedback_collected_at?: string | null;
  notes?: string | null;
}

interface Car {
  id: number;
  model: string;
  variant?: string | null;
  color?: string | null;
  price_inr?: number | string | null;
}

function carSlug(model: string): string {
  return model.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
}
function carImageUrl(model: string): string {
  return `${import.meta.env.BASE_URL}cars/${carSlug(model)}.jpg`;
}
function fmtPriceInr(v: number | string | null | undefined): string {
  if (v == null || v === "") return "—";
  const n = typeof v === "string" ? Number(v) : v;
  if (!Number.isFinite(n)) return String(v);
  return n.toLocaleString("en-IN", { style: "currency", currency: "INR", maximumFractionDigits: 0 });
}

function toIST(iso: string): Date {
  // Shift UTC to IST by adding 5:30. Returns a Date whose UTC fields equal IST wall-clock.
  return new Date(new Date(iso).getTime() + IST_OFFSET_MIN * 60_000);
}
function istDayKey(iso: string): string {
  const d = toIST(iso);
  return `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, "0")}-${String(d.getUTCDate()).padStart(2, "0")}`;
}
function istTimeKey(iso: string): string {
  const d = toIST(iso);
  return `${String(d.getUTCHours()).padStart(2, "0")}:${String(d.getUTCMinutes()).padStart(2, "0")}`;
}
function fmtDayLabel(key: string): { weekday: string; day: string; month: string } {
  const [y, m, d] = key.split("-").map(Number);
  const dt = new Date(Date.UTC(y, m - 1, d));
  return {
    weekday: dt.toLocaleDateString("en-US", { weekday: "short", timeZone: "UTC" }),
    day: String(d).padStart(2, "0"),
    month: dt.toLocaleDateString("en-US", { month: "short", timeZone: "UTC" }),
  };
}
function addDaysKey(key: string, days: number): string {
  const [y, m, d] = key.split("-").map(Number);
  const dt = new Date(Date.UTC(y, m - 1, d + days));
  return `${dt.getUTCFullYear()}-${String(dt.getUTCMonth() + 1).padStart(2, "0")}-${String(dt.getUTCDate()).padStart(2, "0")}`;
}

export function CalendarView() {
  const [drives, setDrives] = useState<TestDrive[]>([]);
  const [cars, setCars] = useState<Car[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [weekStart, setWeekStart] = useState<string | null>(null);
  const [selected, setSelected] = useState<TestDrive | null>(null);
  const [modelFilter, setModelFilter] = useState<string>("");

  useEffect(() => {
    let cancelled = false;
    setLoading(true);
    Promise.all([
      fetchRdbmsLookupRecords(CALENDAR_LOOKUPS.TEST_DRIVES.rdbmsTemplateUuid, {
        workflowId: WORKFLOW_NUMERIC_ID,
        activityId: ACTIVITY_IDS.INIT_ACTIVITY,
        fieldId: CALENDAR_LOOKUPS.TEST_DRIVES.fieldId,
        limit: 1000,
      }),
      fetchRdbmsLookupRecords(CALENDAR_LOOKUPS.CARS.rdbmsTemplateUuid, {
        workflowId: WORKFLOW_NUMERIC_ID,
        activityId: ACTIVITY_IDS.INIT_ACTIVITY,
        fieldId: CALENDAR_LOOKUPS.CARS.fieldId,
        limit: 100,
      }),
    ])
      .then(([td, c]) => {
        if (cancelled) return;
        setDrives((td.records as unknown as TestDrive[]) ?? []);
        setCars((c.records as unknown as Car[]) ?? []);
        const days = (td.records as unknown as TestDrive[])
          .map((r) => istDayKey(r.slot_start))
          .sort();
        setWeekStart(days[0] ?? null);
      })
      .catch((e: any) => !cancelled && setError(e?.message ?? "Failed to load"))
      .finally(() => !cancelled && setLoading(false));
    return () => { cancelled = true; };
  }, []);

  const carById = useMemo(() => {
    const m = new Map<number, Car>();
    cars.forEach((c) => m.set(Number(c.id), c));
    return m;
  }, [cars]);

  const models = useMemo(() => {
    const set = new Set<string>();
    cars.forEach((c) => c.model && set.add(c.model));
    return Array.from(set).sort();
  }, [cars]);

  const visibleCars = useMemo(
    () => (modelFilter ? cars.filter((c) => c.model === modelFilter) : cars),
    [cars, modelFilter],
  );

  const weekDays = useMemo(() => {
    if (!weekStart) return [];
    return Array.from({ length: 7 }, (_, i) => addDaysKey(weekStart, i));
  }, [weekStart]);

  // time-slot keys present in the data, sorted
  const timeSlots = useMemo(() => {
    const set = new Set<string>();
    drives.forEach((d) => set.add(istTimeKey(d.slot_start)));
    return Array.from(set).sort();
  }, [drives]);

  // index drives by (day, time, car) for O(1) lookup
  const grid = useMemo(() => {
    const m = new Map<string, TestDrive>();
    drives.forEach((d) => {
      const key = `${istDayKey(d.slot_start)}|${istTimeKey(d.slot_start)}|${d.car_id}`;
      m.set(key, d);
    });
    return m;
  }, [drives]);

  const visibleCarIds = useMemo(() => new Set(visibleCars.map((c) => Number(c.id))), [visibleCars]);

  // For the visible week, count bookings per day for the header summary.
  const bookingsByDay = useMemo(() => {
    const m = new Map<string, number>();
    drives.forEach((d) => {
      if (d.status !== "booked") return;
      if (!visibleCarIds.has(Number(d.car_id))) return;
      const k = istDayKey(d.slot_start);
      m.set(k, (m.get(k) ?? 0) + 1);
    });
    return m;
  }, [drives, visibleCarIds]);

  const totalBookings = useMemo(
    () => drives.filter((d) => d.status === "booked" && visibleCarIds.has(Number(d.car_id))).length,
    [drives, visibleCarIds],
  );

  if (loading) {
    return <div className="text-stone-400 text-sm">Loading calendar…</div>;
  }
  if (error) {
    return (
      <div className="px-4 py-3 text-sm" style={{ background: ACCENT_SOFT, color: "#5f0229", border: `1px solid ${ACCENT}` }}>
        Couldn't load calendar: {error}
      </div>
    );
  }
  if (!weekStart || timeSlots.length === 0) {
    return <div className="text-stone-400 text-sm">No slots configured.</div>;
  }

  return (
    <>
      {/* Header — page title + week nav */}
      <div className="mb-6 flex items-end justify-between gap-4 flex-wrap">
        <div>
          <div className="text-[11px] font-semibold uppercase tracking-[0.15em]" style={{ color: ACCENT }}>
            Test-drive lifecycle
          </div>
          <h1 className="text-[24px] font-semibold tracking-tight leading-tight mt-1.5" style={{ color: INK }}>
            Slots calendar
          </h1>
        </div>
        <div className="flex items-center gap-3 flex-wrap">
          <div className="relative">
            <select
              value={modelFilter}
              onChange={(e) => setModelFilter(e.target.value)}
              className="h-9 pl-3 pr-8 text-[12.5px] font-semibold bg-white appearance-none cursor-pointer focus:outline-none"
              style={{ border: `1px solid ${TM_BORDER}`, color: INK, borderRadius: 4 }}
            >
              <option value="">All models</option>
              {models.map((m) => <option key={m} value={m}>{m}</option>)}
            </select>
            <span className="absolute right-2.5 top-1/2 -translate-y-1/2 text-stone-400 pointer-events-none text-[10px]">▾</span>
          </div>
          <button
            onClick={() => setWeekStart((k) => k && addDaysKey(k, -7))}
            className="h-9 w-9 inline-flex items-center justify-center bg-white hover:bg-stone-50 transition-colors"
            style={{ border: `1px solid ${TM_BORDER}`, color: INK }}
            aria-label="Previous week"
          >
            <ChevronLeft size={16} />
          </button>
          <div className="text-[13px] font-semibold tabular-nums px-3" style={{ color: INK }}>
            {fmtDayLabel(weekDays[0]).day} {fmtDayLabel(weekDays[0]).month} — {fmtDayLabel(weekDays[6]).day} {fmtDayLabel(weekDays[6]).month}
          </div>
          <button
            onClick={() => setWeekStart((k) => k && addDaysKey(k, 7))}
            className="h-9 w-9 inline-flex items-center justify-center bg-white hover:bg-stone-50 transition-colors"
            style={{ border: `1px solid ${TM_BORDER}`, color: INK }}
            aria-label="Next week"
          >
            <ChevronRight size={16} />
          </button>
        </div>
      </div>

      {/* Legend */}
      <div className="mb-4 flex items-center gap-5 text-[11.5px] text-stone-500">
        <div className="flex items-center gap-2">
          <span className="w-3 h-3" style={{ background: ACCENT }} />
          Booked
        </div>
        <div className="flex items-center gap-2">
          <span className="w-3 h-3 bg-white" style={{ border: `1px solid ${TM_BORDER}` }} />
          Available
        </div>
        <div className="ml-auto text-stone-400">
          {totalBookings} bookings across {weekDays.length} days
        </div>
      </div>

      {/* Grid */}
      <div className="bg-white overflow-x-auto" style={{ border: `1px solid ${TM_BORDER}` }}>
        <table className="w-full" style={{ tableLayout: "fixed", borderCollapse: "collapse" }}>
          <colgroup>
            <col style={{ width: 80 }} />
            {weekDays.map((d) => <col key={d} />)}
          </colgroup>
          <thead>
            <tr>
              <th className="text-left px-3 py-3 text-[10px] font-semibold uppercase tracking-[0.12em] text-stone-400" style={{ borderBottom: `1px solid ${TM_BORDER}` }}>
                IST
              </th>
              {weekDays.map((dk) => {
                const lbl = fmtDayLabel(dk);
                const count = bookingsByDay.get(dk) ?? 0;
                return (
                  <th key={dk} className="text-left px-3 py-3" style={{ borderBottom: `1px solid ${TM_BORDER}`, borderLeft: `1px solid ${TM_BORDER}` }}>
                    <div className="flex items-baseline justify-between gap-2">
                      <div>
                        <div className="text-[10px] font-semibold uppercase tracking-[0.12em] text-stone-400">{lbl.weekday}</div>
                        <div className="text-[15px] font-bold leading-none mt-1 tabular-nums" style={{ color: INK }}>
                          {lbl.day} <span className="text-[11px] font-medium text-stone-400 ml-0.5">{lbl.month}</span>
                        </div>
                      </div>
                      {count > 0 && (
                        <span className="text-[10px] font-bold tabular-nums text-white px-1.5 py-0.5" style={{ background: ACCENT }}>
                          {count}
                        </span>
                      )}
                    </div>
                  </th>
                );
              })}
            </tr>
          </thead>
          <tbody>
            {timeSlots.map((tk) => (
              <tr key={tk}>
                <td className="px-3 py-3 align-top text-[12px] font-semibold tabular-nums text-stone-500" style={{ borderTop: `1px solid ${TM_BORDER}` }}>
                  {tk}
                </td>
                {weekDays.map((dk) => (
                  <td key={dk + tk} className="px-2 py-2 align-top" style={{ borderTop: `1px solid ${TM_BORDER}`, borderLeft: `1px solid ${TM_BORDER}` }}>
                    <div className="grid grid-cols-1 gap-1">
                      {visibleCars.map((c) => {
                        const cell = grid.get(`${dk}|${tk}|${Number(c.id)}`);
                        if (!cell) {
                          return (
                            <div key={c.id} className="h-7 px-2 flex items-center text-[10.5px] text-stone-300" style={{ border: `1px dashed ${TM_BORDER}` }}>
                              —
                            </div>
                          );
                        }
                        const booked = cell.status === "booked";
                        return (
                          <button
                            key={c.id}
                            onClick={() => booked && setSelected(cell)}
                            className={`h-7 px-2 flex items-center justify-between gap-2 text-[10.5px] font-medium transition-colors ${booked ? "cursor-pointer" : "cursor-default"}`}
                            style={
                              booked
                                ? { background: ACCENT, color: "white" }
                                : { background: "white", color: "#a8a29e", border: `1px solid ${TM_BORDER}` }
                            }
                            title={booked ? `${cell.customer_name ?? "Booked"} · ${c.model}` : `Available · ${c.model}`}
                          >
                            <span className="truncate">{c.model}</span>
                            {booked && cell.customer_name && (
                              <span className="truncate font-semibold text-white/90">
                                {cell.customer_name.split(" ")[0]}
                              </span>
                            )}
                          </button>
                        );
                      })}
                    </div>
                  </td>
                ))}
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      <BookingPanel
        drive={selected}
        car={selected ? carById.get(Number(selected.car_id)) : undefined}
        onClose={() => setSelected(null)}
      />
    </>
  );
}

function BookingPanel({ drive, car, onClose }: { drive: TestDrive | null; car: Car | undefined; onClose: () => void }) {
  const open = !!drive;
  return (
    <>
      <div
        className={`fixed inset-0 z-40 transition-opacity duration-200 ${open ? "opacity-100" : "opacity-0 pointer-events-none"}`}
        style={{ background: "rgba(6,31,92,0.35)" }}
        onClick={onClose}
      />
      <aside
        className={`fixed top-0 right-0 bottom-0 z-50 w-full max-w-md bg-white shadow-2xl flex flex-col transition-transform duration-200 ease-out ${open ? "translate-x-0" : "translate-x-full"}`}
        style={{ borderLeft: `1px solid ${TM_BORDER}` }}
        role="dialog"
        aria-hidden={!open}
      >
        {drive && <BookingPanelBody drive={drive} car={car} onClose={onClose} />}
      </aside>
    </>
  );
}

function BookingPanelBody({ drive, car, onClose }: { drive: TestDrive; car: Car | undefined; onClose: () => void }) {
  const day = fmtDayLabel(istDayKey(drive.slot_start));
  const time = `${istTimeKey(drive.slot_start)} – ${istTimeKey(drive.slot_end)} IST`;
  const hasFeedback = drive.feedback_rating != null || !!drive.feedback_liked_most || !!drive.feedback_concern || drive.feedback_would_recommend != null;
  const completed = !!drive.completed_at;
  return (
    <>
      <div className="relative px-6 py-5 text-white shrink-0" style={{ background: TM_NAVY }}>
        <span className="absolute top-0 left-0 bottom-0 w-1.5" style={{ background: ACCENT }} />
        <div className="flex items-start justify-between gap-3">
          <div>
            <div className="text-[11px] font-semibold uppercase tracking-[0.15em]" style={{ color: ACCENT_SOFT }}>
              Booking
            </div>
            <div className="text-[22px] font-bold leading-tight mt-1">
              {drive.customer_name ?? "—"}
            </div>
            <div className="mt-2 text-[12.5px] text-white/80 flex items-center gap-2 flex-wrap">
              <CalendarIcon size={13} />
              <span className="font-semibold">{day.weekday} {day.day} {day.month}</span>
              <span className="text-white/40">·</span>
              <span className="tabular-nums">{time}</span>
            </div>
          </div>
          <button
            onClick={onClose}
            className="text-white/70 hover:text-white transition-colors shrink-0"
            aria-label="Close"
          >
            <X size={18} />
          </button>
        </div>
      </div>

      <div className="overflow-y-auto flex-1">
        {/* Car image hero */}
        {car && (
          <div className="relative w-full bg-stone-100" style={{ aspectRatio: "16 / 9" }}>
            <img
              src={carImageUrl(car.model)}
              alt={car.model}
              className="absolute inset-0 w-full h-full object-cover"
              onError={(e) => {
                const img = e.currentTarget as HTMLImageElement;
                const fallback = `${import.meta.env.BASE_URL}cars/xuv700.jpg`;
                if (img.src.endsWith(fallback)) { img.style.display = "none"; return; }
                img.src = fallback;
              }}
            />
            <div className="absolute inset-x-0 bottom-0 px-5 py-3" style={{ background: "linear-gradient(to top, rgba(6,31,92,0.85), transparent)" }}>
              <div className="text-white text-[18px] font-bold leading-none">{car.model}</div>
              {car.variant && <div className="text-white/80 text-[12px] mt-1">{car.variant}</div>}
            </div>
          </div>
        )}

        <PanelSection label="Vehicle">
          <Row label="Model">
            <span className="font-semibold" style={{ color: INK }}>{car?.model ?? "—"}</span>
          </Row>
          <Row label="Variant">{car?.variant || "—"}</Row>
          <Row label="Color">
            {car?.color ? (
              <span className="inline-flex items-center gap-2">
                <span className="w-3 h-3 rounded-full" style={{ background: colorSwatch(car.color), border: "1px solid rgba(0,0,0,0.1)" }} />
                {car.color}
              </span>
            ) : "—"}
          </Row>
          <Row label="Ex-showroom">
            <span className="font-semibold tabular-nums" style={{ color: INK }}>{fmtPriceInr(car?.price_inr)}</span>
          </Row>
        </PanelSection>

        <PanelSection label="Customer">
          <Row label="Name">
            <span className="font-semibold" style={{ color: INK }}>{drive.customer_name ?? "—"}</span>
          </Row>
          <Row label="Phone">
            {drive.customer_phone ? (
              <a href={`tel:${drive.customer_phone}`} className="inline-flex items-center gap-1.5 font-semibold" style={{ color: ACCENT }}>
                <Phone size={12} />
                {drive.customer_phone}
              </a>
            ) : "—"}
          </Row>
        </PanelSection>

        <PanelSection label="Booking">
          <Row label="Status">
            <StatusPill status={completed ? "Completed" : "Booked"} tone={completed ? "completed" : "booked"} />
          </Row>
          <Row label="Slot">
            <span className="font-semibold tabular-nums" style={{ color: INK }}>{day.weekday} {day.day} {day.month}, {time}</span>
          </Row>
          <Row label="Booked at">
            {drive.booked_at ? new Date(drive.booked_at).toLocaleString("en-IN", { dateStyle: "medium", timeStyle: "short" }) : "—"}
          </Row>
          {completed && (
            <Row label="Completed at">
              {new Date(drive.completed_at!).toLocaleString("en-IN", { dateStyle: "medium", timeStyle: "short" })}
            </Row>
          )}
          {drive.notes && <Row label="Notes">{drive.notes}</Row>}
        </PanelSection>

        <PanelSection label="Feedback">
          {hasFeedback ? (
            <>
              {drive.feedback_rating != null && (
                <Row label="Rating">
                  <RatingStars value={Number(drive.feedback_rating)} />
                </Row>
              )}
              {drive.feedback_would_recommend != null && (
                <Row label="Recommends">
                  <StatusPill
                    status={drive.feedback_would_recommend ? "Yes" : "No"}
                    tone={drive.feedback_would_recommend ? "completed" : "failed"}
                  />
                </Row>
              )}
              {drive.feedback_liked_most && <Row label="Liked most">{drive.feedback_liked_most}</Row>}
              {drive.feedback_concern && <Row label="Concern">{drive.feedback_concern}</Row>}
              {drive.feedback_collected_at && (
                <Row label="Collected at">
                  {new Date(drive.feedback_collected_at).toLocaleString("en-IN", { dateStyle: "medium", timeStyle: "short" })}
                </Row>
              )}
            </>
          ) : (
            <div className="text-[12.5px] text-stone-400 italic px-1">
              {completed ? "No feedback captured yet." : "Feedback will appear here after the drive is completed."}
            </div>
          )}
        </PanelSection>
      </div>
    </>
  );
}

function PanelSection({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <section className="px-6 py-5" style={{ borderBottom: `1px solid ${TM_BORDER}` }}>
      <div className="text-[10px] font-bold uppercase tracking-[0.15em] text-stone-400 mb-3">{label}</div>
      <div className="space-y-3">{children}</div>
    </section>
  );
}

function StatusPill({ status, tone }: { status: string; tone: "booked" | "completed" | "failed" }) {
  const palette: Record<string, { bg: string; fg: string; dot: string }> = {
    booked:    { bg: ACCENT_SOFT, fg: "#5f0229", dot: ACCENT },
    completed: { bg: "#e8f5ec",  fg: "#0f5132", dot: "#2f855a" },
    failed:    { bg: "#fde8e8",  fg: "#7f1d1d", dot: "#dc2626" },
  };
  const p = palette[tone];
  return (
    <span className="inline-flex items-center gap-1.5 px-2 py-1 text-[11px] font-bold uppercase tracking-[0.04em]" style={{ background: p.bg, color: p.fg, borderRadius: 4 }}>
      <span className="w-1.5 h-1.5 rounded-full" style={{ background: p.dot }} />
      {status}
    </span>
  );
}

function RatingStars({ value }: { value: number }) {
  const v = Math.max(0, Math.min(5, Math.round(value)));
  return (
    <span className="inline-flex items-center gap-1.5">
      <span className="text-[14px] tabular-nums" style={{ color: ACCENT, letterSpacing: 1 }}>
        {"★".repeat(v)}<span className="text-stone-300">{"★".repeat(5 - v)}</span>
      </span>
      <span className="text-[11px] font-semibold tabular-nums text-stone-500">{v}/5</span>
    </span>
  );
}

function colorSwatch(color: string): string {
  const c = color.toLowerCase();
  if (c.includes("red") || c.includes("tango")) return "#c62828";
  if (c.includes("white")) return "#f5f5f5";
  if (c.includes("black") || c.includes("napoli") || c.includes("stealth")) return "#1a1a1a";
  if (c.includes("silver") || c.includes("grey") || c.includes("gray")) return "#9ca3af";
  if (c.includes("blue")) return "#1e3a8a";
  return "#9ca3af";
}

function Row({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <div className="flex items-baseline gap-4 text-[13px]">
      <div className="w-24 shrink-0 text-[11px] font-semibold uppercase tracking-[0.05em] text-stone-500">{label}</div>
      <div className="flex-1 min-w-0 break-words" style={{ color: INK }}>{children}</div>
    </div>
  );
}
