"use client";

import { useEffect, useState } from "react";
import { toast } from "sonner";
import { Trash2 } from "lucide-react";

import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Checkbox } from "@/components/ui/checkbox";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { ConfirmDeleteDialog } from "@/components/confirm-delete-dialog";
import {
  createScheduledTodo,
  deleteScheduledTodo,
  getScheduledTodoForEdit,
  updateScheduledTodo,
} from "@/lib/actions/scheduled-todos";
import type { RecurrenceInput } from "@/lib/validation/scheduled-todo";

const TITLE_MAX = 100;
const WEEKDAY_LABELS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
const MONTH_LABELS = [
  "January", "February", "March", "April", "May", "June",
  "July", "August", "September", "October", "November", "December",
];
const FREQUENCY_UNIT: Record<RecurrenceInput["frequency"], string> = {
  DAILY: "day(s)",
  WEEKLY: "week(s)",
  MONTHLY: "month(s)",
  YEARLY: "year(s)",
};

/** "YYYY-MM-DD" for today in the browser's own local calendar -- just a
 * sensible default for the date input, which the user can change anyway. */
function todayDateKey(): string {
  const d = new Date();
  const localMidnight = new Date(d.getTime() - d.getTimezoneOffset() * 60_000);
  return localMidnight.toISOString().slice(0, 10);
}

export function ScheduledTodoDialog({
  open,
  onOpenChange,
  projectId,
  scheduledTodoId,
  onSaved,
  onDeleted,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  projectId: string | null;
  // null = creating a new one; set = editing an existing one.
  scheduledTodoId: string | null;
  onSaved: () => void;
  onDeleted: () => void;
}) {
  const [title, setTitle] = useState("");
  const [details, setDetails] = useState("");
  const [startDate, setStartDate] = useState(todayDateKey());
  const [isRecurring, setIsRecurring] = useState(false);
  const [frequency, setFrequency] = useState<RecurrenceInput["frequency"]>("WEEKLY");
  const [interval, setInterval] = useState(1);
  const [daysOfWeek, setDaysOfWeek] = useState<number[]>([]);
  const [dayOfMonth, setDayOfMonth] = useState(1);
  const [month, setMonth] = useState(1);
  const [endType, setEndType] = useState<"never" | "until" | "count">("never");
  const [endDate, setEndDate] = useState("");
  const [endCount, setEndCount] = useState(10);

  const [loading, setLoading] = useState(false);
  const [pending, setPending] = useState(false);
  const [confirmDeleteOpen, setConfirmDeleteOpen] = useState(false);

  useEffect(() => {
    if (!open) return;

    if (!scheduledTodoId) {
      setTitle("");
      setDetails("");
      setStartDate(todayDateKey());
      setIsRecurring(false);
      setFrequency("WEEKLY");
      setInterval(1);
      setDaysOfWeek([]);
      setDayOfMonth(1);
      setMonth(1);
      setEndType("never");
      setEndDate("");
      setEndCount(10);
      return;
    }

    setLoading(true);
    getScheduledTodoForEdit(scheduledTodoId)
      .then((todo) => {
        setTitle(todo.title);
        setDetails(todo.details ?? "");
        setStartDate(todo.startDate);
        const recurrence = todo.recurrence;
        setIsRecurring(!!recurrence);
        setFrequency(recurrence?.frequency ?? "WEEKLY");
        setInterval(recurrence?.interval ?? 1);
        setDaysOfWeek(recurrence?.daysOfWeek ?? []);
        setDayOfMonth(recurrence?.dayOfMonth ?? 1);
        setMonth(recurrence?.month ?? 1);
        setEndType(recurrence?.end.type ?? "never");
        setEndDate(recurrence?.end.type === "until" ? recurrence.end.date : "");
        setEndCount(recurrence?.end.type === "count" ? recurrence.end.count : 10);
      })
      .catch(() => toast.error("Couldn't load scheduled to-do."))
      .finally(() => setLoading(false));
  }, [open, scheduledTodoId]);

  function toggleDayOfWeek(day: number) {
    setDaysOfWeek((prev) => (prev.includes(day) ? prev.filter((d) => d !== day) : [...prev, day].sort()));
  }

  function buildRecurrence(): RecurrenceInput | undefined {
    if (!isRecurring) return undefined;
    return {
      frequency,
      interval,
      daysOfWeek: frequency === "WEEKLY" ? daysOfWeek : undefined,
      dayOfMonth: frequency === "MONTHLY" || frequency === "YEARLY" ? dayOfMonth : undefined,
      month: frequency === "YEARLY" ? month : undefined,
      end:
        endType === "until"
          ? { type: "until", date: endDate }
          : endType === "count"
            ? { type: "count", count: endCount }
            : { type: "never" },
    };
  }

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    const trimmedTitle = title.trim();
    if (!trimmedTitle) return;
    if (isRecurring && frequency === "WEEKLY" && daysOfWeek.length === 0) {
      toast.error("Pick at least one day of the week.");
      return;
    }
    if (isRecurring && endType === "until" && !endDate) {
      toast.error("Pick an end date.");
      return;
    }

    setPending(true);
    try {
      if (scheduledTodoId) {
        await updateScheduledTodo(scheduledTodoId, {
          title: trimmedTitle,
          details: details.trim() || null,
          startDate,
          recurrence: buildRecurrence() ?? null,
        });
      } else {
        await createScheduledTodo(
          { projectId },
          { title: trimmedTitle, details: details.trim() || undefined, startDate, recurrence: buildRecurrence() }
        );
      }
      onSaved();
      onOpenChange(false);
    } catch {
      toast.error(`Couldn't ${scheduledTodoId ? "update" : "add"} scheduled to-do. Try again.`);
    } finally {
      setPending(false);
    }
  }

  async function handleDelete() {
    if (!scheduledTodoId) return;
    setPending(true);
    try {
      await deleteScheduledTodo(scheduledTodoId);
      onDeleted();
      onOpenChange(false);
    } catch {
      toast.error("Couldn't delete scheduled to-do. Try again.");
    } finally {
      setPending(false);
    }
  }

  return (
    <>
      <Dialog open={open} onOpenChange={onOpenChange}>
        <DialogContent className="sm:max-w-lg">
          <DialogHeader>
            <DialogTitle>{scheduledTodoId ? "Edit scheduled to-do" : "Add scheduled to-do"}</DialogTitle>
          </DialogHeader>

          {loading ? (
            <p className="p-6 text-center text-sm text-muted-foreground">Loading…</p>
          ) : (
            <form onSubmit={handleSubmit} className="space-y-4">
              <div className="space-y-2">
                <Label htmlFor="scheduled-title">Title</Label>
                <Input
                  id="scheduled-title"
                  value={title}
                  maxLength={TITLE_MAX}
                  autoFocus
                  onChange={(e) => setTitle(e.target.value)}
                  placeholder="e.g. Take out the trash"
                />
              </div>

              <div className="space-y-2">
                <Label htmlFor="scheduled-details">Details (optional)</Label>
                <Textarea
                  id="scheduled-details"
                  value={details}
                  onChange={(e) => setDetails(e.target.value)}
                  rows={2}
                  className="resize-none"
                />
              </div>

              <div className="space-y-2">
                <Label htmlFor="scheduled-date">
                  {isRecurring ? "Starts on" : "Date"}
                </Label>
                <Input
                  id="scheduled-date"
                  type="date"
                  value={startDate}
                  onChange={(e) => setStartDate(e.target.value)}
                  required
                />
              </div>

              <label className="flex items-center gap-2 text-sm font-medium">
                <Checkbox checked={isRecurring} onCheckedChange={(c) => setIsRecurring(!!c)} />
                Repeat on a recurring schedule
              </label>

              {isRecurring && (
                <div className="space-y-4 rounded-lg border p-3">
                  <div className="flex items-end gap-2">
                    <div className="space-y-2">
                      <Label>Every</Label>
                      <Input
                        type="number"
                        min={1}
                        max={365}
                        value={interval}
                        onChange={(e) => setInterval(Math.max(1, Number(e.target.value) || 1))}
                        className="w-20"
                      />
                    </div>
                    <div className="space-y-2">
                      <Label className="sr-only">Frequency</Label>
                      <Select
                        value={frequency}
                        onValueChange={(v) => v && setFrequency(v as RecurrenceInput["frequency"])}
                      >
                        <SelectTrigger className="w-32">
                          <SelectValue />
                        </SelectTrigger>
                        <SelectContent>
                          <SelectItem value="DAILY">{FREQUENCY_UNIT.DAILY}</SelectItem>
                          <SelectItem value="WEEKLY">{FREQUENCY_UNIT.WEEKLY}</SelectItem>
                          <SelectItem value="MONTHLY">{FREQUENCY_UNIT.MONTHLY}</SelectItem>
                          <SelectItem value="YEARLY">{FREQUENCY_UNIT.YEARLY}</SelectItem>
                        </SelectContent>
                      </Select>
                    </div>
                  </div>

                  {frequency === "WEEKLY" && (
                    <div className="space-y-2">
                      <Label>On these days</Label>
                      <div className="flex gap-1">
                        {WEEKDAY_LABELS.map((label, day) => (
                          <button
                            key={day}
                            type="button"
                            aria-pressed={daysOfWeek.includes(day)}
                            onClick={() => toggleDayOfWeek(day)}
                            className={cn(
                              "flex size-8 items-center justify-center rounded-md border text-xs font-medium transition-colors",
                              daysOfWeek.includes(day)
                                ? "border-primary bg-primary text-primary-foreground"
                                : "border-input text-muted-foreground hover:bg-accent hover:text-accent-foreground"
                            )}
                          >
                            {label}
                          </button>
                        ))}
                      </div>
                    </div>
                  )}

                  {(frequency === "MONTHLY" || frequency === "YEARLY") && (
                    <div className="flex items-end gap-2">
                      {frequency === "YEARLY" && (
                        <div className="space-y-2">
                          <Label className="sr-only">Month</Label>
                          <Select
                            value={String(month)}
                            onValueChange={(v) => v && setMonth(Number(v))}
                          >
                            <SelectTrigger className="w-36">
                              <SelectValue />
                            </SelectTrigger>
                            <SelectContent>
                              {MONTH_LABELS.map((label, i) => (
                                <SelectItem key={label} value={String(i + 1)}>
                                  {label}
                                </SelectItem>
                              ))}
                            </SelectContent>
                          </Select>
                        </div>
                      )}
                      <div className="space-y-2">
                        <Label>Day</Label>
                        <Input
                          type="number"
                          min={1}
                          max={31}
                          value={dayOfMonth}
                          onChange={(e) =>
                            setDayOfMonth(Math.min(31, Math.max(1, Number(e.target.value) || 1)))
                          }
                          className="w-20"
                        />
                      </div>
                    </div>
                  )}

                  <div className="space-y-2">
                    <Label>Ends</Label>
                    <RadioGroup
                      value={endType}
                      onValueChange={(v) => v && setEndType(v as "never" | "until" | "count")}
                    >
                      <label className="flex items-center gap-2 text-sm">
                        <RadioGroupItem value="never" />
                        Never
                      </label>
                      <label className="flex items-center gap-2 text-sm">
                        <RadioGroupItem value="until" />
                        On date
                        {endType === "until" && (
                          <Input
                            type="date"
                            value={endDate}
                            onChange={(e) => setEndDate(e.target.value)}
                            className="ml-1 w-auto"
                          />
                        )}
                      </label>
                      <label className="flex items-center gap-2 text-sm">
                        <RadioGroupItem value="count" />
                        After
                        {endType === "count" && (
                          <Input
                            type="number"
                            min={1}
                            max={999}
                            value={endCount}
                            onChange={(e) => setEndCount(Math.max(1, Number(e.target.value) || 1))}
                            className="ml-1 w-20"
                          />
                        )}
                        occurrence(s)
                      </label>
                    </RadioGroup>
                  </div>
                </div>
              )}

              <DialogFooter className={cn(scheduledTodoId && "sm:justify-between")}>
                {scheduledTodoId && (
                  <Button
                    type="button"
                    variant="ghost"
                    className="text-destructive hover:text-destructive gap-2"
                    onClick={() => setConfirmDeleteOpen(true)}
                    disabled={pending}
                  >
                    <Trash2 className="size-4" />
                    Delete
                  </Button>
                )}
                <Button type="submit" disabled={pending || !title.trim()}>
                  {pending ? "Saving…" : scheduledTodoId ? "Save" : "Add scheduled to-do"}
                </Button>
              </DialogFooter>
            </form>
          )}
        </DialogContent>
      </Dialog>

      <ConfirmDeleteDialog
        open={confirmDeleteOpen}
        onOpenChange={setConfirmDeleteOpen}
        title="Delete scheduled to-do?"
        description={
          isRecurring
            ? `Delete "${title}" and all of its remaining occurrences? This can't be undone.`
            : `Delete "${title}"? This can't be undone.`
        }
        onConfirm={handleDelete}
      />
    </>
  );
}
