"use client";

import { useEffect, useMemo, useRef, useState } from "react";
import { Modal } from "@/components/ui/modal";
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 { cn } from "@/lib/utils";
import type {
  CalendarEvent,
  EventResponseStatus,
  MeetingTemplate,
  TeamMember,
} from "@/types";
import type {
  ParticipantAvailability,
  SuggestedMeetingSlot,
} from "@/hooks/use-events";

const EVENT_COLORS = [
  { label: "Default", value: "#6366f1" },
  { label: "Red", value: "#ef4444" },
  { label: "Orange", value: "#f97316" },
  { label: "Green", value: "#22c55e" },
  { label: "Blue", value: "#3b82f6" },
  { label: "Purple", value: "#8b5cf6" },
  { label: "Pink", value: "#ec4899" },
];

interface EventFormProps {
  open: boolean;
  onClose: () => void;
  onSubmit: (data: EventFormData) => Promise<void>;
  onDelete?: () => Promise<void>;
  event?: CalendarEvent | null;
  defaultDate?: Date;
  members?: TeamMember[];
  readOnly?: boolean;
  templates?: MeetingTemplate[];
  initialTemplateId?: string | null;
  currentUserId?: string | null;
  onRespond?: (status: EventResponseStatus) => Promise<void>;
  onCheckAvailability?: (input: {
    participantIds: string[];
    start: string;
    end: string;
    excludeEventId?: string | null;
  }) => Promise<ParticipantAvailability[]>;
  onFindBestSlots?: (input: {
    participantIds: string[];
    date: string;
    durationMinutes: number;
    excludeEventId?: string | null;
  }) => Promise<SuggestedMeetingSlot[]>;
}

export interface EventFormData {
  title: string;
  description: string;
  start_time: string;
  end_time: string;
  all_day: boolean;
  color: string | null;
  participant_ids: string[];
}

function toLocalDate(date: Date) {
  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}`;
}

export function EventForm({
  open,
  onClose,
  onSubmit,
  onDelete,
  event,
  defaultDate,
  members = [],
  readOnly = false,
  templates = [],
  initialTemplateId = null,
  currentUserId = null,
  onRespond,
  onCheckAvailability,
  onFindBestSlots,
}: EventFormProps) {
  const isEditing = !!event;
  const now = defaultDate || new Date();

  const [title, setTitle] = useState(event?.title || "");
  const [description, setDescription] = useState(event?.description || "");
  const [allDay, setAllDay] = useState(event?.all_day ?? false);
  const [startDate, setStartDate] = useState(
    event
      ? toLocalDate(new Date(event.start_time))
      : toLocalDate(now)
  );
  const [startTime, setStartTime] = useState(
    event && !event.all_day
      ? new Date(event.start_time).toTimeString().slice(0, 5)
      : "09:00"
  );
  const [endDate, setEndDate] = useState(
    event
      ? toLocalDate(new Date(event.end_time))
      : toLocalDate(now)
  );
  const [endTime, setEndTime] = useState(
    event && !event.all_day
      ? new Date(event.end_time).toTimeString().slice(0, 5)
      : "10:00"
  );
  const [color, setColor] = useState(event?.color || EVENT_COLORS[0].value);
  const [participantIds, setParticipantIds] = useState<string[]>(
    event?.participants?.map((participant) => participant.user_id) || []
  );
  const [submitting, setSubmitting] = useState(false);
  const [selectedTemplateId, setSelectedTemplateId] = useState(initialTemplateId || "");
  const [availability, setAvailability] = useState<ParticipantAvailability[]>([]);
  const [availabilityLoading, setAvailabilityLoading] = useState(false);
  const [suggestedSlots, setSuggestedSlots] = useState<SuggestedMeetingSlot[]>([]);
  const [suggestionsLoading, setSuggestionsLoading] = useState(false);
  const [responseSubmitting, setResponseSubmitting] = useState(false);

  const currentParticipant = useMemo(
    () =>
      currentUserId
        ? event?.participants?.find((participant) => participant.user_id === currentUserId) ||
          null
        : null,
    [currentUserId, event?.participants]
  );
  const templateBaseStartRef = useRef({
    date: event ? toLocalDate(new Date(event.start_time)) : toLocalDate(now),
    time:
      event && !event.all_day
        ? new Date(event.start_time).toTimeString().slice(0, 5)
        : "09:00",
  });

  useEffect(() => {
    if (!initialTemplateId) return;
    const template = templates.find((item) => item.id === initialTemplateId);
    if (!template) return;

    setSelectedTemplateId(template.id);
    setTitle(template.name);
    setDescription(template.description || "");
    setColor(template.color || EVENT_COLORS[0].value);
    setAllDay(template.all_day);
    setParticipantIds(template.participants?.map((participant) => participant.id) || []);

    if (!template.all_day) {
      const start = new Date(
        `${templateBaseStartRef.current.date}T${templateBaseStartRef.current.time}`
      );
      const nextEnd = new Date(start.getTime() + template.duration_minutes * 60 * 1000);
      setEndDate(toLocalDate(nextEnd));
      setEndTime(nextEnd.toTimeString().slice(0, 5));
    }
  }, [initialTemplateId, templates]);

  function applyTemplate(templateId: string) {
    if (!templateId) {
      setSelectedTemplateId("");
      return;
    }

    const template = templates.find((item) => item.id === templateId);
    if (!template) return;

    setSelectedTemplateId(template.id);
    setTitle(template.name);
    setDescription(template.description || "");
    setColor(template.color || EVENT_COLORS[0].value);
    setAllDay(template.all_day);
    setParticipantIds(template.participants?.map((participant) => participant.id) || []);

    if (!template.all_day) {
      const start = new Date(`${startDate}T${startTime}`);
      const nextEnd = new Date(start.getTime() + template.duration_minutes * 60 * 1000);
      setEndDate(toLocalDate(nextEnd));
      setEndTime(nextEnd.toTimeString().slice(0, 5));
    }
  }

  async function handleCheckAvailability() {
    if (!onCheckAvailability || participantIds.length === 0) return;

    const start = allDay
      ? new Date(`${startDate}T00:00:00`).toISOString()
      : new Date(`${startDate}T${startTime}`).toISOString();
    const end = allDay
      ? new Date(`${endDate}T23:59:59`).toISOString()
      : new Date(`${endDate}T${endTime}`).toISOString();

    setAvailabilityLoading(true);
    try {
      const result = await onCheckAvailability({
        participantIds,
        start,
        end,
        excludeEventId: event?.id || null,
      });
      setAvailability(result);
    } finally {
      setAvailabilityLoading(false);
    }
  }

  async function handleFindBestSlots() {
    if (!onFindBestSlots || participantIds.length === 0 || allDay) return;

    setSuggestionsLoading(true);
    try {
      const result = await onFindBestSlots({
        participantIds,
        date: startDate,
        durationMinutes: Math.max(
          15,
          Math.round(
            (new Date(`${endDate}T${endTime}`).getTime() -
              new Date(`${startDate}T${startTime}`).getTime()) /
              (60 * 1000)
          ) || 60
        ),
        excludeEventId: event?.id || null,
      });
      setSuggestedSlots(result);
    } finally {
      setSuggestionsLoading(false);
    }
  }

  async function handleRespond(status: EventResponseStatus) {
    if (!onRespond || !currentParticipant || responseSubmitting) return;
    setResponseSubmitting(true);
    try {
      await onRespond(status);
    } finally {
      setResponseSubmitting(false);
    }
  }

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (readOnly || !title.trim() || submitting) return;

    setSubmitting(true);

    const start = allDay
      ? new Date(startDate + "T00:00:00").toISOString()
      : new Date(startDate + "T" + startTime).toISOString();
    const end = allDay
      ? new Date(endDate + "T23:59:59").toISOString()
      : new Date(endDate + "T" + endTime).toISOString();

    try {
      await onSubmit({
        title: title.trim(),
        description: description.trim(),
        start_time: start,
        end_time: end,
        all_day: allDay,
        color,
        participant_ids: participantIds,
      });
      setSubmitting(false);
      onClose();
    } catch (err) {
      setSubmitting(false);
      // If the parent throws (e.g. time block conflict), keep the form open
      if ((err as Error)?.message !== "TIME_BLOCK_CONFLICT") throw err;
    }
  }

  return (
    <Modal
      open={open}
      onClose={onClose}
      title={isEditing ? "Edit event" : "New event"}
      className="max-w-md"
    >
      <form onSubmit={handleSubmit} className="space-y-4">
        <Input
          placeholder="Event title"
          value={title}
          onChange={(e) => setTitle(e.target.value)}
          className="text-base font-medium border-0 px-0 focus-visible:ring-0 shadow-none"
          autoFocus
          required
          disabled={readOnly}
        />

        <Textarea
          placeholder="Add a description..."
          value={description}
          onChange={(e) => setDescription(e.target.value)}
          className="min-h-[50px] border-0 px-0 focus-visible:ring-0 shadow-none text-sm"
          disabled={readOnly}
        />

        {templates.length > 0 && !isEditing && (
          <div className="space-y-1.5">
            <Label className="text-xs text-muted-foreground">Meeting template</Label>
            <select
              value={selectedTemplateId}
              onChange={(event) => applyTemplate(event.target.value)}
              className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
              disabled={readOnly}
            >
              <option value="">Start from scratch</option>
              {templates.map((template) => (
                <option key={template.id} value={template.id}>
                  {template.name}
                </option>
              ))}
            </select>
          </div>
        )}

        {/* All day toggle */}
        <label className="flex items-center gap-2 cursor-pointer">
          <input
            type="checkbox"
            checked={allDay}
            onChange={(e) => setAllDay(e.target.checked)}
            className="rounded border-input"
            disabled={readOnly}
          />
          <span className="text-sm">All day</span>
        </label>

        {/* Date/time fields */}
        <div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
          <div className="space-y-1">
            <Label className="text-xs text-muted-foreground">Start date</Label>
            <Input
              type="date"
              value={startDate}
              onChange={(e) => setStartDate(e.target.value)}
              required
              disabled={readOnly}
            />
          </div>
          {!allDay && (
            <div className="space-y-1">
              <Label className="text-xs text-muted-foreground">
                Start time
              </Label>
              <Input
                type="time"
                value={startTime}
                onChange={(e) => setStartTime(e.target.value)}
                required
                disabled={readOnly}
              />
            </div>
          )}
          <div className="space-y-1">
            <Label className="text-xs text-muted-foreground">End date</Label>
            <Input
              type="date"
              value={endDate}
              onChange={(e) => setEndDate(e.target.value)}
              required
              disabled={readOnly}
            />
          </div>
          {!allDay && (
            <div className="space-y-1">
              <Label className="text-xs text-muted-foreground">End time</Label>
              <Input
                type="time"
                value={endTime}
                onChange={(e) => setEndTime(e.target.value)}
                required
                disabled={readOnly}
              />
            </div>
          )}
        </div>

        {/* Color */}
        <div className="space-y-1.5">
          <Label className="text-xs text-muted-foreground">Color</Label>
          <div className="flex gap-1.5">
            {EVENT_COLORS.map((c) => (
              <button
                key={c.value}
                type="button"
                onClick={() => setColor(c.value)}
                disabled={readOnly}
                className={cn(
                  "h-6 w-6 rounded-full cursor-pointer transition-transform",
                  color === c.value &&
                    "scale-110 ring-2 ring-ring ring-offset-2"
                )}
                style={{ backgroundColor: c.value }}
                title={c.label}
              />
            ))}
          </div>
        </div>

        {members.length > 0 && (
          <div className="space-y-1.5">
            <Label className="text-xs text-muted-foreground">Participants</Label>
            <div className="flex flex-wrap gap-2">
              {members.map((member) => {
                const selected = participantIds.includes(member.user_id);
                const label =
                  member.profile?.full_name || member.profile?.email || "Team member";

                return (
                  <button
                    key={member.user_id}
                    type="button"
                    onClick={() =>
                      setParticipantIds((prev) =>
                        prev.includes(member.user_id)
                          ? prev.filter((id) => id !== member.user_id)
                          : [...prev, member.user_id]
                      )
                    }
                    disabled={readOnly}
                    className={cn(
                      "rounded-full border px-2.5 py-1 text-xs transition-colors",
                      selected
                        ? "border-primary bg-primary/10 text-primary"
                        : "border-border bg-background text-muted-foreground hover:text-foreground",
                      readOnly && "cursor-not-allowed opacity-70"
                    )}
                  >
                    {label}
                  </button>
                );
              })}
            </div>
          </div>
        )}

        {participantIds.length > 0 && !allDay && (
          <div className="space-y-3 rounded-xl border border-border/60 bg-background/60 p-4">
            <div className="flex flex-wrap items-center justify-between gap-2">
              <div>
                <p className="text-sm font-medium">Availability</p>
                <p className="text-xs text-muted-foreground">
                  Check whether the selected participants are already busy and find the cleanest slot.
                </p>
              </div>
              <div className="flex flex-wrap gap-2">
                <Button
                  type="button"
                  size="sm"
                  variant="outline"
                  onClick={() => void handleCheckAvailability()}
                  disabled={availabilityLoading}
                >
                  {availabilityLoading ? "Checking..." : "Check availability"}
                </Button>
                <Button
                  type="button"
                  size="sm"
                  variant="outline"
                  onClick={() => void handleFindBestSlots()}
                  disabled={suggestionsLoading}
                >
                  {suggestionsLoading ? "Finding..." : "Find best slots"}
                </Button>
              </div>
            </div>

            {availability.length > 0 && (
              <div className="space-y-2">
                {availability.map((participant) => (
                  <div
                    key={participant.user_id}
                    className="rounded-lg border border-border/60 bg-background px-3 py-2 text-sm"
                  >
                    <div className="flex items-center justify-between gap-3">
                      <span>{participant.label}</span>
                      <span
                        className={cn(
                          "rounded-full px-2 py-0.5 text-[11px] font-medium",
                          participant.busy
                            ? "bg-red-500/10 text-red-700"
                            : "bg-emerald-500/10 text-emerald-700"
                        )}
                      >
                        {participant.busy ? "Busy" : "Free"}
                      </span>
                    </div>
                    {participant.conflicts.length > 0 && (
                      <p className="mt-1 text-xs text-muted-foreground">
                        {participant.conflicts
                          .slice(0, 2)
                          .map((conflict) => conflict.title)
                          .join(", ")}
                      </p>
                    )}
                  </div>
                ))}
              </div>
            )}

            {suggestedSlots.length > 0 && (
              <div className="space-y-2">
                <p className="text-xs font-medium uppercase tracking-[0.16em] text-muted-foreground">
                  Suggested slots
                </p>
                <div className="flex flex-wrap gap-2">
                  {suggestedSlots.map((slot) => {
                    const start = new Date(slot.start);
                    const end = new Date(slot.end);
                    return (
                      <button
                        key={slot.start}
                        type="button"
                        onClick={() => {
                          setStartDate(toLocalDate(start));
                          setEndDate(toLocalDate(end));
                          setStartTime(start.toTimeString().slice(0, 5));
                          setEndTime(end.toTimeString().slice(0, 5));
                        }}
                        className="rounded-full border border-border px-3 py-1 text-xs transition-colors hover:bg-accent"
                      >
                        {start.toTimeString().slice(0, 5)} - {end.toTimeString().slice(0, 5)}
                        {" · "}
                        {slot.unavailableCount === 0
                          ? "Everyone free"
                          : `${slot.availableCount} free`}
                      </button>
                    );
                  })}
                </div>
              </div>
            )}
          </div>
        )}

        {currentParticipant && (
          <div className="space-y-2 rounded-xl border border-border/60 bg-background/60 p-4">
            <div>
              <p className="text-sm font-medium">Your RSVP</p>
              <p className="text-xs text-muted-foreground">
                Keep the organizer updated with your current availability.
              </p>
            </div>
            <div className="flex flex-wrap gap-2">
              {(["accepted", "declined", "pending"] as EventResponseStatus[]).map((status) => (
                <Button
                  key={status}
                  type="button"
                  size="sm"
                  variant={currentParticipant.response_status === status ? "default" : "outline"}
                  onClick={() => void handleRespond(status)}
                  disabled={!onRespond || responseSubmitting}
                >
                  {status === "accepted"
                    ? "Accept"
                    : status === "declined"
                    ? "Decline"
                    : "Maybe later"}
                </Button>
              ))}
            </div>
          </div>
        )}

        {/* Actions */}
        <div className="flex items-center justify-between pt-2">
          <div>
            {isEditing && onDelete && !readOnly && (
              <Button
                type="button"
                variant="ghost"
                className="text-destructive hover:text-destructive"
                onClick={async () => {
                  await onDelete();
                  onClose();
                }}
              >
                Delete
              </Button>
            )}
          </div>
          <div className="flex gap-2">
            <Button type="button" variant="ghost" onClick={onClose}>
              {readOnly ? "Close" : "Cancel"}
            </Button>
            {!readOnly && (
              <Button type="submit" disabled={!title.trim() || submitting}>
              {submitting
                ? isEditing
                  ? "Saving..."
                  : "Creating..."
                : isEditing
                ? "Save"
                : "Create"}
              </Button>
            )}
          </div>
        </div>
      </form>
    </Modal>
  );
}
