'use client';

import { useCallback, useEffect, useState } from 'react';
import type { ComponentType } from 'react';
import FullCalendarBase from '@fullcalendar/react';
import type { DateSelectArg, DatesSetArg, EventClickArg, EventContentArg, EventInput } from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';
import timeGridPlugin from '@fullcalendar/timegrid';
import interactionPlugin from '@fullcalendar/interaction';
import trLocale from '@fullcalendar/core/locales/tr.js';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { SelectNative } from '@/components/ui/select-native';
import { apiFetchJson } from '@/lib/auth';
import { useBranches } from '@/lib/hooks/use-branches';

const FullCalendar = FullCalendarBase as unknown as ComponentType<Record<string, unknown>>;

type ApiActivity = {
  id: string;
  classroomId: string;
  title: string;
  description: string | null;
  startsOn: string;
  endsOn: string;
};

type ClassroomOpt = { id: string; name: string; branchName?: string };

interface SchoolCalendarEvent extends EventInput {
  id: string;
  extendedProps: {
    description: string;
  };
}

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

function defaultVisibleRange(): { from: string; to: string } {
  const n = new Date();
  const from = new Date(n.getFullYear(), n.getMonth() - 1, 1);
  const to = new Date(n.getFullYear(), n.getMonth() + 2, 0);
  return { from: toYmdLocal(from), to: toYmdLocal(to) };
}

function addOneDayYmd(iso: string): string {
  const d = new Date(`${iso}T12:00:00`);
  d.setDate(d.getDate() + 1);
  return toYmdLocal(d);
}

function apiRowToFcEvent(a: ApiActivity): SchoolCalendarEvent {
  const description = a.description ?? '';
  const base = {
    backgroundColor: 'transparent',
    borderColor: 'transparent',
    textColor: 'inherit',
  };
  if (a.startsOn === a.endsOn) {
    return {
      id: a.id,
      title: a.title,
      start: a.startsOn,
      allDay: true,
      extendedProps: { description },
      ...base,
    };
  }
  return {
    id: a.id,
    title: a.title,
    start: a.startsOn,
    end: addOneDayYmd(a.endsOn),
    allDay: true,
    extendedProps: { description },
    ...base,
  };
}

function exclusiveEndToInclusive(endExclusive?: Date | null): string {
  if (!endExclusive) return '';
  const d = new Date(endExclusive);
  d.setDate(d.getDate() - 1);
  return toYmdLocal(d);
}

const EVENT_TONE_COUNT = 8;

/** Aynı etkinlik her zaman aynı renkte (API id üzerinden). */
function eventToneIndex(id: string): number {
  let h = 2166136261;
  for (let i = 0; i < id.length; i += 1) {
    h ^= id.charCodeAt(i);
    h = Math.imul(h, 16777619);
  }
  return Math.abs(h >>> 0) % EVENT_TONE_COUNT;
}

function renderEventContent(eventInfo: EventContentArg) {
  const id = String(eventInfo.event.id ?? '');
  const tone = eventToneIndex(id);
  return (
    <div className={`calendar-event-pill calendar-event-tone-${tone} fc-event-main`}>
      <span className="calendar-event-accent" aria-hidden />
      <div className="calendar-event-body">
        {eventInfo.timeText ? <span className="calendar-event-time">{eventInfo.timeText}</span> : null}
        <span className="calendar-event-title">{eventInfo.event.title}</span>
      </div>
    </div>
  );
}

export function SchoolEventsCalendar() {
  const { branches } = useBranches();
  const [classrooms, setClassrooms] = useState<ClassroomOpt[]>([]);
  const [branchId, setBranchId] = useState('');
  const [classroomId, setClassroomId] = useState('');
  const [visibleRange, setVisibleRange] = useState(defaultVisibleRange);
  const [events, setEvents] = useState<SchoolCalendarEvent[]>([]);
  const [loading, setLoading] = useState(false);
  const [listError, setListError] = useState('');
  const [open, setOpen] = useState(false);
  const [selectedId, setSelectedId] = useState<string | null>(null);
  const [title, setTitle] = useState('');
  const [description, setDescription] = useState('');
  const [startDate, setStartDate] = useState('');
  const [endDate, setEndDate] = useState('');
  const [saving, setSaving] = useState(false);
  const [formError, setFormError] = useState('');

  useEffect(() => {
    setClassroomId('');
    const q = new URLSearchParams({ limit: '200' });
    if (branchId) q.set('branchId', branchId);
    apiFetchJson<ClassroomOpt[]>(`/v1/admin/classrooms?${q.toString()}`).then((res) => {
      setClassrooms(Array.isArray(res.data) ? res.data : []);
    });
  }, [branchId]);

  const loadActivities = useCallback(async () => {
    if (!classroomId) {
      setEvents([]);
      return;
    }
    setLoading(true);
    setListError('');
    const q = new URLSearchParams({
      classroomId,
      from: visibleRange.from,
      to: visibleRange.to,
    });
    const res = await apiFetchJson<ApiActivity[]>(`/v1/admin/classroom-activities?${q.toString()}`);
    if (res.error) {
      setListError(res.error);
      setEvents([]);
    } else {
      const rows = Array.isArray(res.data) ? res.data : [];
      setEvents(rows.map(apiRowToFcEvent));
    }
    setLoading(false);
  }, [classroomId, visibleRange.from, visibleRange.to]);

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

  const onDatesSet = useCallback((arg: DatesSetArg) => {
    const from = toYmdLocal(arg.start);
    const endExclusive = arg.end;
    const lastVisible = new Date(endExclusive);
    lastVisible.setDate(lastVisible.getDate() - 1);
    const to = toYmdLocal(lastVisible);
    setVisibleRange({ from, to });
  }, []);

  const resetForm = useCallback(() => {
    setSelectedId(null);
    setTitle('');
    setDescription('');
    setStartDate('');
    setEndDate('');
    setFormError('');
  }, []);

  const handleDateSelect = useCallback(
    (selectInfo: DateSelectArg) => {
      if (!classroomId) {
        setListError('Önce bir sınıf seçin.');
        selectInfo.view.calendar.unselect();
        return;
      }
      resetForm();
      setStartDate(selectInfo.startStr);
      if (selectInfo.end) {
        const endInclusive = exclusiveEndToInclusive(selectInfo.end);
        setEndDate(endInclusive || selectInfo.startStr);
      } else {
        setEndDate(selectInfo.startStr);
      }
      setOpen(true);
      selectInfo.view.calendar.unselect();
    },
    [classroomId, resetForm],
  );

  const handleEventClick = useCallback((clickInfo: EventClickArg) => {
    const ev = clickInfo.event;
    setSelectedId(ev.id);
    setTitle(ev.title);
    const startStr = ev.start ? toYmdLocal(ev.start) : '';
    setStartDate(startStr);
    if (ev.allDay) {
      if (ev.end) {
        const inc = exclusiveEndToInclusive(ev.end);
        setEndDate(inc || startStr);
      } else {
        setEndDate(startStr);
      }
    } else if (ev.end) {
      setEndDate(toYmdLocal(ev.end));
    } else {
      setEndDate(startStr);
    }
    const row = events.find((e) => e.id === ev.id);
    setDescription(row?.extendedProps?.description ?? '');
    setOpen(true);
  }, [events]);

  const handleSave = useCallback(async () => {
    if (!title.trim() || !startDate || !classroomId) return;
    setSaving(true);
    setFormError('');
    const ends = endDate && endDate >= startDate ? endDate : startDate;
    const payloadBase = {
      title: title.trim(),
      startsOn: startDate,
      endsOn: ends,
    };
    let res;
    if (selectedId) {
      res = await apiFetchJson<ApiActivity>(`/v1/admin/classroom-activities/${selectedId}`, {
        method: 'PATCH',
        body: JSON.stringify({
          ...payloadBase,
          description: description.trim() === '' ? null : description.trim(),
        }),
      });
    } else {
      res = await apiFetchJson<ApiActivity>('/v1/admin/classroom-activities', {
        method: 'POST',
        body: JSON.stringify({
          classroomId,
          ...payloadBase,
          ...(description.trim() ? { description: description.trim() } : {}),
        }),
      });
    }
    setSaving(false);
    if (res.error) {
      setFormError(res.error);
      return;
    }
    setOpen(false);
    resetForm();
    await loadActivities();
  }, [title, description, startDate, endDate, selectedId, classroomId, resetForm, loadActivities]);

  const handleDelete = useCallback(async () => {
    if (!selectedId) return;
    setSaving(true);
    setFormError('');
    const res = await apiFetchJson(`/v1/admin/classroom-activities/${selectedId}`, { method: 'DELETE' });
    setSaving(false);
    if (res.error) {
      setFormError(res.error);
      return;
    }
    setOpen(false);
    resetForm();
    await loadActivities();
  }, [selectedId, resetForm, loadActivities]);

  return (
    <>
      <div className="border-b border-gray-200 px-4 py-4 dark:border-gray-800 sm:px-6">
        <div className="flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-end">
          {branches.length > 0 && (
            <div className="min-w-[200px] space-y-1">
              <Label className="text-sm text-zinc-600 dark:text-zinc-400">Şube</Label>
              <SelectNative
                className="h-11 w-full min-w-[180px] rounded-lg sm:max-w-xs"
                value={branchId}
                onChange={(e) => setBranchId(e.target.value)}
              >
                <option value="">Tüm şubeler</option>
                {branches.map((b) => (
                  <option key={b.id} value={b.id}>
                    {b.name}
                  </option>
                ))}
              </SelectNative>
            </div>
          )}
          <div className="min-w-[220px] space-y-1">
            <Label className="text-sm text-zinc-600 dark:text-zinc-400">Sınıf</Label>
            <SelectNative
              className="h-11 w-full min-w-[200px] rounded-lg sm:max-w-md"
              value={classroomId}
              onChange={(e) => setClassroomId(e.target.value)}
            >
              <option value="">{branchId ? 'Sınıf seçin…' : 'Önce şube seçin…'}</option>
              {classrooms.map((c) => (
                <option key={c.id} value={c.id}>
                  {c.name}
                  {!branchId && c.branchName ? ` · ${c.branchName}` : ''}
                </option>
              ))}
            </SelectNative>
          </div>
          {loading ? (
            <span className="text-sm text-gray-500 dark:text-gray-400">Yükleniyor…</span>
          ) : null}
        </div>
        {listError ? <p className="mt-2 text-sm text-red-600 dark:text-red-400">{listError}</p> : null}
        {!classroomId ? (
          <p className="mt-2 text-sm text-gray-500 dark:text-gray-400">
            Etkinlikleri veritabanında görmek ve düzenlemek için sınıf seçin.
          </p>
        ) : null}
      </div>

      <div className="custom-calendar">
        <FullCalendar
          plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]}
          initialView="dayGridMonth"
          locale={trLocale}
          headerToolbar={{
            left: 'prev,next',
            center: 'title',
            right: 'dayGridMonth,timeGridWeek,timeGridDay',
          }}
          buttonText={{
            today: 'bugün',
            month: 'ay',
            week: 'hafta',
            day: 'gün',
          }}
          titleFormat={{ year: 'numeric', month: 'long' }}
          events={events}
          selectable={!!classroomId}
          selectMirror
          select={handleDateSelect}
          eventClick={handleEventClick}
          eventContent={renderEventContent}
          datesSet={onDatesSet}
          height="auto"
        />
      </div>

      <Dialog
        open={open}
        onOpenChange={(next) => {
          setOpen(next);
          if (!next) resetForm();
        }}
      >
        <DialogContent className="max-w-[700px] gap-0 p-6 sm:p-8">
          <DialogHeader className="space-y-2 text-left">
            <DialogTitle className="text-xl dark:text-white">
              {selectedId ? 'Etkinliği düzenle' : 'Etkinlik ekle'}
            </DialogTitle>
            <DialogDescription className="text-sm text-gray-500 dark:text-gray-400">
              Kayıtlar sunucuda saklanır; seçili sınıf ve görünür tarih aralığına göre listelenir.
            </DialogDescription>
          </DialogHeader>

          <div className="mt-6 space-y-5">
            {formError ? (
              <div className="rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700 dark:border-red-900/50 dark:bg-red-950/40 dark:text-red-200">
                {formError}
              </div>
            ) : null}
            <div className="space-y-1.5">
              <Label htmlFor="ev-title">Başlık</Label>
              <Input
                id="ev-title"
                value={title}
                onChange={(e) => setTitle(e.target.value)}
                placeholder="Örn. Bahar şenliği"
                className="h-11"
              />
            </div>

            <div className="space-y-1.5">
              <Label htmlFor="ev-desc">Açıklama (isteğe bağlı)</Label>
              <Textarea
                id="ev-desc"
                value={description}
                onChange={(e) => setDescription(e.target.value)}
                rows={3}
                className="resize-y"
                placeholder="Kısa notlar…"
              />
            </div>

            <div className="grid gap-4 sm:grid-cols-2">
              <div className="space-y-1.5">
                <Label htmlFor="ev-start">Başlangıç</Label>
                <Input
                  id="ev-start"
                  type="date"
                  value={startDate}
                  onChange={(e) => setStartDate(e.target.value)}
                  className="h-11"
                />
              </div>
              <div className="space-y-1.5">
                <Label htmlFor="ev-end">Bitiş (dahil)</Label>
                <Input
                  id="ev-end"
                  type="date"
                  value={endDate}
                  onChange={(e) => setEndDate(e.target.value)}
                  className="h-11"
                />
              </div>
            </div>
            <p className="text-xs text-gray-500 dark:text-gray-500">
              Tüm gün etkinliklerde bitiş, son günü içerir. Tek gün için başlangıç ve bitişi aynı seçin.
            </p>
          </div>

          <DialogFooter className="mt-8 flex-col gap-2 sm:flex-row sm:justify-between">
            <div>
              {selectedId ? (
                <Button
                  type="button"
                  variant="secondary"
                  className="text-red-600 hover:bg-red-50 dark:hover:bg-red-950/40"
                  onClick={() => void handleDelete()}
                  disabled={saving}
                >
                  Sil
                </Button>
              ) : (
                <span />
              )}
            </div>
            <div className="flex flex-col gap-2 sm:flex-row">
              <Button type="button" variant="secondary" onClick={() => setOpen(false)} disabled={saving}>
                Vazgeç
              </Button>
              <Button
                type="button"
                onClick={() => void handleSave()}
                disabled={!title.trim() || !startDate || saving}
              >
                {saving ? 'Kaydediliyor…' : selectedId ? 'Kaydet' : 'Ekle'}
              </Button>
            </div>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  );
}
