"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { CalendarDays, Trash2, X } from "lucide-react";
import { cn } from "@/lib/utils";
import { Modal } from "@/components/ui/modal";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { useEvents } from "@/hooks/use-events";

/* ─── Types ─── */

interface TimeBlock {
  id: string;
  title: string;
  date: string; // YYYY-MM-DD
  startTime: string; // HH:MM (24h)
  endTime: string; // HH:MM (24h)
  color: string; // hex
  projectOrTask?: string;
}

/* ─── Constants ─── */

const STORAGE_KEY = "mindavio_time_blocks";

const BLOCK_COLORS = [
  { name: "Indigo", value: "#6366f1" },
  { name: "Rose", value: "#f43f5e" },
  { name: "Emerald", value: "#10b981" },
  { name: "Amber", value: "#f59e0b" },
  { name: "Violet", value: "#8b5cf6" },
  { name: "Cyan", value: "#06b6d4" },
];

/** First hour displayed */
const START_HOUR = 7;
/** Last hour displayed (exclusive) */
const END_HOUR = 22;
const HOUR_COUNT = END_HOUR - START_HOUR; // 15
const HOUR_HEIGHT = 48; // px per hour

/* ─── Helpers ─── */

function toDateString(date: Date): string {
  const y = date.getFullYear();
  const m = String(date.getMonth() + 1).padStart(2, "0");
  const d = String(date.getDate()).padStart(2, "0");
  return `${y}-${m}-${d}`;
}

function getWeekDays(): Date[] {
  const today = new Date();
  const dow = today.getDay(); // 0=Sun
  // Monday of current week — set to noon to avoid DST/midnight edge cases
  const monday = new Date(today);
  monday.setHours(12, 0, 0, 0);
  monday.setDate(today.getDate() - ((dow + 6) % 7));
  return Array.from({ length: 7 }, (_, i) => {
    const d = new Date(monday);
    d.setDate(monday.getDate() + i);
    return d;
  });
}

function isoToLocalDateStr(iso: string): string {
  return toDateString(new Date(iso));
}

function isoToLocalTimeStr(iso: string): string {
  const d = new Date(iso);
  return `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
}

function timeToMinutes(time: string): number {
  const [h, m] = time.split(":").map(Number);
  return h * 60 + m;
}

function minutesToTime(minutes: number): string {
  const h = Math.floor(minutes / 60);
  const m = minutes % 60;
  return `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`;
}

function blockTop(startTime: string): number {
  const startMin = timeToMinutes(startTime);
  const offsetMin = startMin - START_HOUR * 60;
  return Math.max(0, (offsetMin / 60) * HOUR_HEIGHT);
}

function blockHeight(startTime: string, endTime: string): number {
  const startMin = timeToMinutes(startTime);
  const endMin = timeToMinutes(endTime);
  const diff = Math.max(0, endMin - startMin);
  return (diff / 60) * HOUR_HEIGHT;
}

function nowTop(): number {
  const now = new Date();
  const minutes = now.getHours() * 60 + now.getMinutes();
  const offsetMin = minutes - START_HOUR * 60;
  if (offsetMin < 0 || offsetMin > HOUR_COUNT * 60) return -1;
  return (offsetMin / 60) * HOUR_HEIGHT;
}

const DAY_LABELS = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"];

/* ─── Default form state ─── */
interface BlockForm {
  title: string;
  date: string;
  startTime: string;
  endTime: string;
  color: string;
  projectOrTask: string;
}

function defaultForm(date: string, startHour?: number): BlockForm {
  const h = startHour ?? 9;
  return {
    title: "",
    date,
    startTime: minutesToTime(h * 60),
    endTime: minutesToTime(h * 60 + 60),
    color: BLOCK_COLORS[0].value,
    projectOrTask: "",
  };
}

/* ─── Main Component ─── */

export function TimeBlockingPanel() {
  const weekDays = useMemo(() => getWeekDays(), []);
  const todayStr = useMemo(() => toDateString(new Date()), []);

  // Calendar events for the displayed week — shown as occupied slots so a
  // real appointment automatically blocks that time here too, and a new
  // manual block can't be saved on top of it.
  const weekRange = useMemo(() => {
    const start = new Date(weekDays[0]);
    start.setHours(0, 0, 0, 0);
    const end = new Date(weekDays[6]);
    end.setHours(23, 59, 59, 999);
    return { start, end };
  }, [weekDays]);
  const { events: calendarEvents } = useEvents(weekRange.start, weekRange.end);
  const timedEvents = useMemo(
    () =>
      calendarEvents
        .filter((event) => !event.all_day)
        .map((event) => ({
          id: event.id,
          title: event.title,
          date: isoToLocalDateStr(event.start_time),
          startTime: isoToLocalTimeStr(event.start_time),
          endTime: isoToLocalTimeStr(event.end_time),
          color: event.color || "#a1a1aa",
        })),
    [calendarEvents],
  );

  // Start with empty array — identical on server and client → no hydration mismatch
  const [blocks, setBlocks] = useState<TimeBlock[]>([]);
  const hasMounted = useRef(false);

  const [modalOpen, setModalOpen] = useState(false);
  const [form, setForm] = useState<BlockForm>(defaultForm(todayStr));
  const [error, setError] = useState("");
  const [nowY, setNowY] = useState(nowTop());

  const nowIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);

  /* ── Load from localStorage after hydration ── */
  useEffect(() => {
    try {
      const raw = localStorage.getItem(STORAGE_KEY);
      if (raw) {
        const parsed = JSON.parse(raw) as TimeBlock[];
        // queueMicrotask: react-hooks/set-state-in-effect flags calling
        // setBlocks directly in the effect body — defer by one tick.
        if (Array.isArray(parsed)) queueMicrotask(() => setBlocks(parsed));
      }
    } catch {}
  }, []);

  /* ── Persist — skip the very first effect run to avoid overwriting with [] ── */
  useEffect(() => {
    if (!hasMounted.current) {
      hasMounted.current = true;
      return;
    }
    localStorage.setItem(STORAGE_KEY, JSON.stringify(blocks));
  }, [blocks]);

  /* ── Update current-time indicator every minute ── */
  useEffect(() => {
    nowIntervalRef.current = setInterval(() => setNowY(nowTop()), 60_000);
    return () => {
      if (nowIntervalRef.current) clearInterval(nowIntervalRef.current);
    };
  }, []);

  /* ── Handlers ── */
  const openAddModal = useCallback((date: string, startHour?: number) => {
    setError("");
    setForm(defaultForm(date, startHour));
    setModalOpen(true);
  }, []);

  function handleSlotClick(date: string, hourIndex: number) {
    openAddModal(date, START_HOUR + hourIndex);
  }

  function handleSave() {
    if (!form.title.trim()) {
      setError("Bitte einen Titel eingeben.");
      return;
    }
    if (!form.date || !form.startTime || !form.endTime) {
      setError("Bitte Datum, Start- und Endzeit angeben.");
      return;
    }
    if (timeToMinutes(form.endTime) <= timeToMinutes(form.startTime)) {
      setError("Endzeit muss nach der Startzeit liegen.");
      return;
    }
    const startMin = timeToMinutes(form.startTime);
    const endMin = timeToMinutes(form.endTime);
    const conflictingEvent = timedEvents.find((event) => {
      if (event.date !== form.date) return false;
      return startMin < timeToMinutes(event.endTime) && endMin > timeToMinutes(event.startTime);
    });
    if (conflictingEvent) {
      setError(`Überschneidet sich mit dem Termin „${conflictingEvent.title}“.`);
      return;
    }
    const newBlock: TimeBlock = {
      id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
      title: form.title.trim(),
      date: form.date,
      startTime: form.startTime,
      endTime: form.endTime,
      color: form.color,
      projectOrTask: form.projectOrTask.trim() || undefined,
    };
    setBlocks((prev) => [...prev, newBlock]);
    setModalOpen(false);
  }

  function handleDelete(id: string) {
    setBlocks((prev) => prev.filter((b) => b.id !== id));
  }

  return (
    <div className="select-none">
      {/* Grid: time gutter + 7 day columns */}
      <div className="overflow-x-auto">
        <div
          className="grid min-w-[600px]"
          style={{ gridTemplateColumns: `44px repeat(7, 1fr)` }}
        >
          {/* ── Column headers ── */}
          <div /> {/* gutter spacer */}
          {weekDays.map((day, i) => {
            const dateStr = toDateString(day);
            const isToday = dateStr === todayStr;
            return (
              <div key={dateStr} className="px-1 pb-3 text-center">
                <p
                  className={cn(
                    "text-[10px] font-semibold uppercase tracking-widest",
                    isToday ? "text-violet-400" : "text-white/30"
                  )}
                >
                  {DAY_LABELS[i]}
                </p>
                <p
                  className={cn(
                    "mt-0.5 text-[13px] font-bold",
                    isToday ? "text-white" : "text-white/50"
                  )}
                >
                  {day.getDate()}
                </p>
              </div>
            );
          })}

          {/* ── Time rows ── */}
          {/* Gutter column */}
          <div className="relative" style={{ height: HOUR_COUNT * HOUR_HEIGHT }}>
            {Array.from({ length: HOUR_COUNT }, (_, i) => (
              <div
                key={i}
                className="absolute right-1 text-[10px] text-white/20 tabular-nums"
                style={{ top: i * HOUR_HEIGHT - 6 }}
              >
                {String(START_HOUR + i).padStart(2, "0")}
              </div>
            ))}
          </div>

          {/* Day columns */}
          {weekDays.map((day) => {
            const dateStr = toDateString(day);
            const isToday = dateStr === todayStr;
            const dayBlocks = blocks.filter((b) => b.date === dateStr);
            const dayEvents = timedEvents.filter((e) => e.date === dateStr);

            return (
              <div
                key={dateStr}
                className={cn(
                  "relative border-l border-white/[0.04]",
                  isToday && "bg-violet-500/[0.03]"
                )}
                style={{ height: HOUR_COUNT * HOUR_HEIGHT }}
              >
                {/* Hour slot lines + click areas */}
                {Array.from({ length: HOUR_COUNT }, (_, hourIdx) => (
                  <div
                    key={hourIdx}
                    onClick={() => handleSlotClick(dateStr, hourIdx)}
                    className="absolute inset-x-0 cursor-pointer border-t border-white/[0.04] transition-colors hover:bg-white/[0.02]"
                    style={{
                      top: hourIdx * HOUR_HEIGHT,
                      height: HOUR_HEIGHT,
                    }}
                  />
                ))}

                {/* Current time indicator */}
                {isToday && nowY >= 0 && (
                  <div
                    className="pointer-events-none absolute inset-x-0 z-20 flex items-center"
                    style={{ top: nowY }}
                  >
                    <div className="h-px flex-1 bg-rose-500/70" />
                    <div className="h-2 w-2 rounded-full bg-rose-500" />
                  </div>
                )}

                {/* Calendar events — occupy their slot automatically, not editable/deletable here */}
                {dayEvents.map((event) => {
                  const top = blockTop(event.startTime);
                  const height = blockHeight(event.startTime, event.endTime);
                  if (height < 4) return null;
                  return (
                    <div
                      key={`event-${event.id}`}
                      title={`${event.title} (Termin, ${event.startTime}–${event.endTime})`}
                      className="absolute inset-x-1 z-10 overflow-hidden rounded-lg px-2 py-1"
                      style={{
                        top,
                        height,
                        backgroundColor: `${event.color}18`,
                        border: `1px dashed ${event.color}80`,
                      }}
                    >
                      <p
                        className="flex items-center gap-1 truncate text-[11px] font-semibold leading-tight"
                        style={{ color: event.color }}
                      >
                        <CalendarDays className="h-2.5 w-2.5 shrink-0" />
                        {event.title}
                      </p>
                      {height >= 28 && (
                        <p className="truncate text-[9px] text-white/40">
                          {event.startTime}–{event.endTime}
                        </p>
                      )}
                    </div>
                  );
                })}

                {/* Time blocks */}
                {dayBlocks.map((block) => {
                  const top = blockTop(block.startTime);
                  const height = blockHeight(block.startTime, block.endTime);
                  if (height < 4) return null;
                  return (
                    <div
                      key={block.id}
                      className="group absolute inset-x-1 z-10 overflow-hidden rounded-lg px-2 py-1"
                      style={{
                        top,
                        height,
                        backgroundColor: `${block.color}22`,
                        borderLeft: `3px solid ${block.color}`,
                      }}
                    >
                      <p
                        className="truncate text-[11px] font-semibold leading-tight"
                        style={{ color: block.color }}
                      >
                        {block.title}
                      </p>
                      {height >= 28 && (
                        <p className="truncate text-[9px] text-white/40">
                          {block.startTime}–{block.endTime}
                        </p>
                      )}
                      {block.projectOrTask && height >= 40 && (
                        <p className="truncate text-[9px] text-white/30">
                          {block.projectOrTask}
                        </p>
                      )}
                      <button
                        onClick={(e) => {
                          e.stopPropagation();
                          handleDelete(block.id);
                        }}
                        className="absolute right-1 top-1 rounded p-0.5 opacity-0 transition-opacity group-hover:opacity-100 hover:bg-white/10"
                        title="Block löschen"
                      >
                        <X className="h-3 w-3 text-white/60" />
                      </button>
                    </div>
                  );
                })}
              </div>
            );
          })}
        </div>
      </div>

      {/* ── Add Modal ── */}
      <Modal
        open={modalOpen}
        onClose={() => setModalOpen(false)}
        title="Time Block hinzufügen"
        className="max-w-md"
      >
        <div className="space-y-4">
          {error && (
            <p className="rounded-lg bg-destructive/10 px-3 py-2 text-sm text-destructive">
              {error}
            </p>
          )}

          {/* Title */}
          <label className="space-y-1 text-sm">
            <span className="text-white/50">Titel</span>
            <Input
              placeholder="Deep Work, Meeting, Pause..."
              value={form.title}
              onChange={(e) => setForm((f) => ({ ...f, title: e.target.value }))}
              autoFocus
              className="border-white/[0.08] bg-white/[0.04] text-white placeholder:text-white/20"
            />
          </label>

          {/* Date */}
          <label className="space-y-1 text-sm">
            <span className="text-white/50">Datum</span>
            <Input
              type="date"
              value={form.date}
              onChange={(e) => setForm((f) => ({ ...f, date: e.target.value }))}
              className="border-white/[0.08] bg-white/[0.04] text-white"
            />
          </label>

          {/* Time range */}
          <div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
            <label className="space-y-1 text-sm">
              <span className="text-white/50">Startzeit</span>
              <Input
                type="time"
                value={form.startTime}
                onChange={(e) => setForm((f) => ({ ...f, startTime: e.target.value }))}
                className="border-white/[0.08] bg-white/[0.04] text-white"
              />
            </label>
            <label className="space-y-1 text-sm">
              <span className="text-white/50">Endzeit</span>
              <Input
                type="time"
                value={form.endTime}
                onChange={(e) => setForm((f) => ({ ...f, endTime: e.target.value }))}
                className="border-white/[0.08] bg-white/[0.04] text-white"
              />
            </label>
          </div>

          {/* Color */}
          <div className="space-y-2">
            <p className="text-sm text-white/50">Farbe</p>
            <div className="flex flex-wrap gap-2">
              {BLOCK_COLORS.map((c) => (
                <button
                  key={c.value}
                  type="button"
                  onClick={() => setForm((f) => ({ ...f, color: c.value }))}
                  title={c.name}
                  className={cn(
                    "h-7 w-7 rounded-full border-2 transition-all",
                    form.color === c.value
                      ? "border-white scale-110"
                      : "border-transparent opacity-60 hover:opacity-100 hover:scale-105"
                  )}
                  style={{ backgroundColor: c.value }}
                />
              ))}
            </div>
          </div>

          {/* Project / Task label */}
          <label className="space-y-1 text-sm">
            <span className="text-white/50">Projekt / Task (optional)</span>
            <Input
              placeholder="z.B. Mindavio, Kundenpräsentation..."
              value={form.projectOrTask}
              onChange={(e) => setForm((f) => ({ ...f, projectOrTask: e.target.value }))}
              className="border-white/[0.08] bg-white/[0.04] text-white placeholder:text-white/20"
            />
          </label>

          <div className="flex justify-end gap-2 pt-1">
            <Button variant="ghost" onClick={() => setModalOpen(false)}>
              Abbrechen
            </Button>
            <Button onClick={handleSave}>Speichern</Button>
          </div>
        </div>
      </Modal>

      {/* Legend */}
      {blocks.length > 0 && (
        <div className="mt-4 flex flex-wrap items-center gap-3">
          <p className="text-[11px] text-white/25">{blocks.length} Block{blocks.length !== 1 ? "s" : ""} diese Woche</p>
          <button
            onClick={() => {
              const weekStrs = new Set(weekDays.map(toDateString));
              if (blocks.filter((b) => weekStrs.has(b.date)).length > 0) {
                setBlocks((prev) => prev.filter((b) => !weekStrs.has(b.date)));
              }
            }}
            className="flex items-center gap-1 rounded-lg px-2 py-1 text-[11px] text-white/20 transition-colors hover:bg-white/[0.04] hover:text-white/40"
          >
            <Trash2 className="h-3 w-3" />
            Woche löschen
          </button>
        </div>
      )}
    </div>
  );
}
