"use client";

import Link from "next/link";
import { useMemo, useState, useTransition } from "react";
import { ChevronLeft, ChevronRight, Loader2, Plus, SquareCheckBig, Trash2 } from "lucide-react";
import { toast } from "sonner";

import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { deleteCalendarEventAction } from "@/lib/appwrite/calendar-actions";
import { cn } from "@/lib/utils";

import { EventFormSheet } from "./event-form-sheet";
import { COLOR_BG, type Customer, type EventRow } from "./types";

type Props = {
  events: EventRow[];
  customers: Customer[];
};

const WEEKDAYS = ["Pzt", "Sal", "Çar", "Per", "Cum", "Cmt", "Paz"];
const MONTH_NAMES = [
  "Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran",
  "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık",
];

function startOfMonthGrid(year: number, month: number): Date {
  // Monday-first grid; first cell is the Monday on/before the 1st
  const first = new Date(year, month, 1);
  const dayIdx = (first.getDay() + 6) % 7; // 0 = Mon
  return new Date(year, month, 1 - dayIdx);
}

function ymd(d: Date): string {
  const pad = (n: number) => String(n).padStart(2, "0");
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
}

export function CalendarClient({ events, customers }: Props) {
  const today = new Date();
  const [cursor, setCursor] = useState(new Date(today.getFullYear(), today.getMonth(), 1));
  const [formOpen, setFormOpen] = useState(false);
  const [editing, setEditing] = useState<EventRow | null>(null);
  const [defaultDate, setDefaultDate] = useState<string | undefined>();
  const [deleting, setDeleting] = useState<EventRow | null>(null);
  const [busy, startTransition] = useTransition();

  const eventsByDay = useMemo(() => {
    const map = new Map<string, EventRow[]>();
    for (const e of events) {
      const start = new Date(e.start);
      const end = new Date(e.end);
      const cur = new Date(start.getFullYear(), start.getMonth(), start.getDate());
      const last = new Date(end.getFullYear(), end.getMonth(), end.getDate());
      while (cur.getTime() <= last.getTime()) {
        const key = ymd(cur);
        const arr = map.get(key) ?? [];
        arr.push(e);
        map.set(key, arr);
        cur.setDate(cur.getDate() + 1);
      }
    }
    return map;
  }, [events]);

  const grid = useMemo(() => {
    const start = startOfMonthGrid(cursor.getFullYear(), cursor.getMonth());
    const days: Date[] = [];
    for (let i = 0; i < 42; i++) {
      const d = new Date(start);
      d.setDate(start.getDate() + i);
      days.push(d);
    }
    return days;
  }, [cursor]);

  const handlePrev = () => setCursor(new Date(cursor.getFullYear(), cursor.getMonth() - 1, 1));
  const handleNext = () => setCursor(new Date(cursor.getFullYear(), cursor.getMonth() + 1, 1));
  const handleToday = () => setCursor(new Date(today.getFullYear(), today.getMonth(), 1));

  const handleAddOnDay = (date: Date) => {
    setEditing(null);
    setDefaultDate(ymd(date));
    setFormOpen(true);
  };

  const handleAddNew = () => {
    setEditing(null);
    setDefaultDate(ymd(today));
    setFormOpen(true);
  };

  const handleEdit = (event: EventRow) => {
    if (event.source === "task") return;
    setEditing(event);
    setDefaultDate(undefined);
    setFormOpen(true);
  };

  const handleDelete = () => {
    if (!deleting) return;
    startTransition(async () => {
      const fd = new FormData();
      fd.set("id", deleting.id);
      const result = await deleteCalendarEventAction(fd);
      if (result.ok) {
        toast.success("Etkinlik silindi.");
        setDeleting(null);
      } else {
        toast.error(result.error ?? "Silme başarısız.");
      }
    });
  };

  const todayKey = ymd(today);

  return (
    <Card>
      <CardContent className="p-4">
        <div className="mb-4 flex flex-col items-center justify-between gap-3 md:flex-row">
          <div className="flex items-center gap-2">
            <Button variant="outline" size="icon" className="size-8" onClick={handlePrev}>
              <ChevronLeft className="size-4" />
            </Button>
            <h2 className="text-lg font-semibold">
              {MONTH_NAMES[cursor.getMonth()]} {cursor.getFullYear()}
            </h2>
            <Button variant="outline" size="icon" className="size-8" onClick={handleNext}>
              <ChevronRight className="size-4" />
            </Button>
            <Button variant="ghost" size="sm" onClick={handleToday}>
              Bugün
            </Button>
          </div>
          <Button onClick={handleAddNew}>
            <Plus className="size-4" />
            Yeni etkinlik
          </Button>
        </div>

        <div className="grid grid-cols-7 gap-px overflow-hidden rounded-md border bg-border">
          {WEEKDAYS.map((wd) => (
            <div
              key={wd}
              className="bg-muted/40 text-muted-foreground py-2 text-center text-xs font-medium"
            >
              {wd}
            </div>
          ))}
          {grid.map((d) => {
            const inMonth = d.getMonth() === cursor.getMonth();
            const key = ymd(d);
            const isToday = key === todayKey;
            const dayEvents = eventsByDay.get(key) ?? [];
            return (
              <div
                key={key}
                className={cn(
                  "bg-card group relative flex min-h-[110px] flex-col gap-1 p-1.5",
                  !inMonth && "bg-muted/30",
                )}
              >
                <div className="flex items-center justify-between">
                  <span
                    className={cn(
                      "inline-flex size-6 items-center justify-center rounded-full text-xs",
                      isToday && "bg-primary text-primary-foreground font-medium",
                      !inMonth && "text-muted-foreground",
                    )}
                  >
                    {d.getDate()}
                  </span>
                  <button
                    type="button"
                    onClick={() => handleAddOnDay(d)}
                    className="text-muted-foreground hover:text-foreground opacity-0 group-hover:opacity-100"
                    aria-label="Bu güne etkinlik ekle"
                  >
                    <Plus className="size-3.5" />
                  </button>
                </div>
                <div className="flex flex-col gap-0.5">
                  {dayEvents.slice(0, 3).map((e) =>
                    e.source === "task" ? (
                      <Link
                        key={e.id}
                        href="/tasks"
                        className={cn(
                          "flex items-center gap-1 truncate rounded border px-1.5 py-0.5 text-left text-xs",
                          COLOR_BG["task"],
                        )}
                        title={e.title}
                      >
                        <SquareCheckBig className="size-3 shrink-0 opacity-70" />
                        <span className="truncate">{e.title}</span>
                      </Link>
                    ) : (
                      <button
                        key={e.id}
                        type="button"
                        onClick={() => handleEdit(e)}
                        className={cn(
                          "truncate rounded border px-1.5 py-0.5 text-left text-xs",
                          COLOR_BG[e.color] ?? COLOR_BG[""],
                        )}
                        title={e.title}
                      >
                        {!e.allDay && (
                          <span className="opacity-70">
                            {new Date(e.start).toLocaleTimeString("tr-TR", {
                              hour: "2-digit",
                              minute: "2-digit",
                            })}{" "}
                          </span>
                        )}
                        {e.title}
                      </button>
                    ),
                  )}
                  {dayEvents.length > 3 && (
                    <span className="text-muted-foreground px-1 text-xs">
                      +{dayEvents.length - 3} daha
                    </span>
                  )}
                </div>
              </div>
            );
          })}
        </div>
      </CardContent>

      <EventFormSheet
        open={formOpen}
        onOpenChange={(v) => {
          setFormOpen(v);
          if (!v) setEditing(null);
        }}
        event={editing}
        defaultDate={defaultDate}
        customers={customers}
        onRequestDelete={(e) => {
          setFormOpen(false);
          setDeleting(e);
        }}
      />

      <Dialog open={Boolean(deleting)} onOpenChange={(v) => !v && setDeleting(null)}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Etkinliği sil</DialogTitle>
            <DialogDescription>
              <strong>{deleting?.title}</strong> kalıcı olarak silinecek.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button variant="outline" onClick={() => setDeleting(null)} disabled={busy}>
              Vazgeç
            </Button>
            <Button variant="destructive" onClick={handleDelete} disabled={busy}>
              {busy ? <Loader2 className="size-4 animate-spin" /> : <Trash2 className="size-4" />}
              Sil
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </Card>
  );
}
