"use client";

import { useEffect, useState, type FormEvent } from "react";
import { JalaliDatePicker } from "@/components/jalali-date-picker/jalali-date-picker";
import { getTodayGregorianIso } from "@/components/jalali-date-picker/utils";
import { Select } from "@/components/select";
import { CategoryPicker } from "@/features/categories/components/category-picker";
import { habitsDict } from "@/features/habits/dict";
import type { Habit, HabitFormValues, HabitFrequency, HabitTargetType } from "@/features/habits/types";
import { getTodayIsoDate, habitToFormValues, isQuantitativeHabitForm, validateHabitForm } from "@/features/habits/utils/habit-helpers";
import { DESCRIPTION_MAX_LENGTH, TITLE_MAX_LENGTH } from "@/lib/field-limits";

type HabitSheetProps = {
  open: boolean;
  mode: "create" | "edit";
  habit?: Habit | null;
  isSubmitting: boolean;
  isDeleting?: boolean;
  onClose: () => void;
  onSubmit: (values: HabitFormValues) => void;
  onDelete?: () => void;
};

const defaultValues: HabitFormValues = {
  name: "",
  description: "",
  category: null,
  unit: "",
  targetType: "AT_LEAST",
  targetValue: "",
  minTargetValue: "",
  maxTargetValue: "",
  frequency: "DAILY",
  daysOfWeek: [],
  allowMultipleLogsPerDay: false,
  reminder: false,
  reminderTime: "09:00",
  isActive: true,
  startedDate: getTodayIsoDate(),
};

const targetTypeOptions = Object.keys(habitsDict.targetTypes) as HabitTargetType[];
const frequencyOptions = Object.keys(habitsDict.frequencies) as HabitFrequency[];

export function HabitSheet({
  open,
  mode,
  habit,
  isSubmitting,
  isDeleting = false,
  onClose,
  onSubmit,
  onDelete,
}: HabitSheetProps) {
  const [values, setValues] = useState<HabitFormValues>(defaultValues);
  const [errors, setErrors] = useState<Partial<Record<keyof HabitFormValues, string>>>({});

  useEffect(() => {
    if (!open) return;

    if (mode === "edit" && habit) {
      setValues(habitToFormValues(habit));
    } else {
      setValues({
        ...defaultValues,
        startedDate: getTodayIsoDate(),
      });
    }

    setErrors({});
  }, [open, mode, habit]);

  useEffect(() => {
    if (!open) return;

    const handleEscape = (event: KeyboardEvent) => {
      if (event.key === "Escape") onClose();
    };

    document.addEventListener("keydown", handleEscape);
    document.body.style.overflow = "hidden";

    return () => {
      document.removeEventListener("keydown", handleEscape);
      document.body.style.overflow = "";
    };
  }, [open, onClose]);

  if (!open) return null;

  const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    const nextErrors = validateHabitForm(values);

    if (Object.keys(nextErrors).length > 0) {
      setErrors(nextErrors);
      return;
    }
    const body = {
      ...values,
      targetType: !values.unit ? "AT_LEAST" : values.targetType,
    };

    onSubmit(body);
  };

  const showDaysOfWeek =
    values.frequency === "WEEKLY" || values.frequency === "CUSTOM";
  const isQuantitative = isQuantitativeHabitForm(values);
  const showRange = isQuantitative && values.targetType === "RANGE";
  const showTargetValue = isQuantitative && !showRange;

  const toggleDay = (day: number) => {
    setValues((current) => ({
      ...current,
      daysOfWeek: current.daysOfWeek.includes(day)
        ? current.daysOfWeek.filter((item) => item !== day)
        : [...current.daysOfWeek, day].sort((a, b) => a - b),
    }));
  };

  return (
    <div className="fixed inset-0 z-[100] flex items-end justify-center bg-black/40 p-0 sm:items-center sm:p-4">
      <button type="button" aria-label={habitsDict.cancel} className="absolute inset-0" onClick={onClose} />

      <div className="relative z-10 flex max-h-[96vh] w-full max-w-lg flex-col overflow-hidden rounded-t-3xl bg-card shadow-soft sm:rounded-3xl">
        <div className="shrink-0 px-6 pt-4">
          <div className="mx-auto mb-4 h-1.5 w-12 rounded-full bg-border sm:hidden" />
          <div className="space-y-1 pb-4 text-center sm:text-start">
            <h2 className="text-xl font-bold text-card-foreground">
              {mode === "create" ? habitsDict.addHabit : habitsDict.editHabit}
            </h2>
            <p className="text-sm text-muted-foreground">{habitsDict.subtitle}</p>
          </div>
        </div>

        <form onSubmit={handleSubmit} className="flex min-h-0 flex-1 flex-col">
          <div className="min-h-0 flex-1 space-y-4 overflow-y-auto px-6 pb-4">
            <div className="space-y-2">
              <label htmlFor="habit-name" className="text-sm font-medium">{habitsDict.nameLabel}</label>
              <input
                id="habit-name"
                value={values.name}
                maxLength={TITLE_MAX_LENGTH}
                onChange={(e) => setValues((c) => ({ ...c, name: e.target.value }))}
                placeholder={habitsDict.namePlaceholder}
                className="h-12 w-full rounded-2xl bg-input px-4 text-sm shadow-soft-sm ring-1 ring-border outline-none focus:ring-2 focus:ring-primary"
              />
              {errors.name ? <p className="text-sm text-destructive">{errors.name}</p> : null}
            </div>

            <div className="space-y-2">
              <label htmlFor="habit-description" className="text-sm font-medium">{habitsDict.descriptionLabel}</label>
              <textarea
                id="habit-description"
                value={values.description}
                maxLength={DESCRIPTION_MAX_LENGTH}
                onChange={(e) => setValues((c) => ({ ...c, description: e.target.value }))}
                placeholder={habitsDict.descriptionPlaceholder}
                rows={2}
                className="w-full rounded-2xl bg-input px-4 py-3 text-sm shadow-soft-sm ring-1 ring-border outline-none focus:ring-2 focus:ring-primary"
              />
              {errors.description ? (
                <p className="text-sm text-destructive">{errors.description}</p>
              ) : null}
            </div>

            <CategoryPicker
              domain="HABIT"
              value={values.category}
              onChange={(category) => setValues((c) => ({ ...c, category }))}
              id="habit-category"
              label={habitsDict.typeLabel}
            />

            <div className="space-y-2">
              <label htmlFor="habit-unit" className="text-sm font-medium">{habitsDict.unitLabel}</label>
              <input
                id="habit-unit"
                value={values.unit}
                onChange={(e) => {
                  const unit = e.target.value;
                  setValues((c) => ({
                    ...c,
                    unit,
                    ...(unit.trim()
                      ? {}
                      : {
                        targetValue: "",
                        minTargetValue: "",
                        maxTargetValue: "",
                      }),
                  }));
                }}
                placeholder={habitsDict.unitPlaceholder}
                className="h-12 w-full rounded-2xl bg-input px-4 text-sm shadow-soft-sm ring-1 ring-border outline-none focus:ring-2 focus:ring-primary"
              />
              {!isQuantitative ? (
                <p className="text-xs text-muted-foreground">
                  {habitsDict.booleanHabitHint}
                </p>
              ) : null}
            </div>

            {isQuantitative ? (
              <>
                <div className="space-y-2">
                  <label htmlFor="habit-target-type" className="text-sm font-medium">{habitsDict.targetTypeLabel}</label>
                  <Select
                    id="habit-target-type"
                    value={values.targetType}
                    onChange={(e) => setValues((c) => ({ ...c, targetType: e.target.value as HabitTargetType }))}
                  >
                    {targetTypeOptions.map((option) => (
                      <option key={option} value={option}>{habitsDict.targetTypes[option]}</option>
                    ))}
                  </Select>
                </div>

                {showTargetValue ? (
                  <div className="space-y-2">
                    <label htmlFor="habit-target-value" className="text-sm font-medium">{habitsDict.targetValueLabel}</label>
                    <input
                      id="habit-target-value"
                      type="number"
                      min={0}
                      dir="ltr"
                      value={values.targetValue}
                      onChange={(e) => setValues((c) => ({ ...c, targetValue: e.target.value }))}
                      className="h-12 w-full rounded-2xl bg-input px-4 text-sm shadow-soft-sm ring-1 ring-border outline-none focus:ring-2 focus:ring-primary"
                    />
                    {errors.targetValue ? <p className="text-sm text-destructive">{errors.targetValue}</p> : null}
                  </div>
                ) : (
                  <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
                    <div className="space-y-2">
                      <label htmlFor="habit-min-target" className="text-sm font-medium">{habitsDict.minTargetValueLabel}</label>
                      <input
                        id="habit-min-target"
                        type="number"
                        min={0}
                        dir="ltr"
                        value={values.minTargetValue}
                        onChange={(e) => setValues((c) => ({ ...c, minTargetValue: e.target.value }))}
                        className="h-12 w-full rounded-2xl bg-input px-4 text-sm shadow-soft-sm ring-1 ring-border outline-none focus:ring-2 focus:ring-primary"
                      />
                    </div>
                    <div className="space-y-2">
                      <label htmlFor="habit-max-target" className="text-sm font-medium">{habitsDict.maxTargetValueLabel}</label>
                      <input
                        id="habit-max-target"
                        type="number"
                        min={0}
                        dir="ltr"
                        value={values.maxTargetValue}
                        onChange={(e) => setValues((c) => ({ ...c, maxTargetValue: e.target.value }))}
                        className="h-12 w-full rounded-2xl bg-input px-4 text-sm shadow-soft-sm ring-1 ring-border outline-none focus:ring-2 focus:ring-primary"
                      />
                    </div>
                    {errors.minTargetValue ? <p className="text-sm text-destructive sm:col-span-2">{errors.minTargetValue}</p> : null}
                  </div>
                )}
              </>
            ) : null}

            <div className="space-y-2">
              <label htmlFor="habit-started-date" className="text-sm font-medium">
                {habitsDict.startedDateLabel}
              </label>
              <JalaliDatePicker
                id="habit-started-date"
                value={values.startedDate}
                maxDate={getTodayGregorianIso()}
                onChange={(startedDate) =>
                  setValues((current) => ({ ...current, startedDate }))
                }
              />
              {errors.startedDate ? (
                <p className="text-sm text-destructive">{errors.startedDate}</p>
              ) : null}
            </div>

            <div className="space-y-2">
              <label htmlFor="habit-frequency" className="text-sm font-medium">{habitsDict.frequencyLabel}</label>
              <Select
                id="habit-frequency"
                value={values.frequency}
                onChange={(e) => setValues((c) => ({ ...c, frequency: e.target.value as HabitFrequency }))}
              >
                {frequencyOptions.map((option) => (
                  <option key={option} value={option}>{habitsDict.frequencies[option]}</option>
                ))}
              </Select>
            </div>

            {showDaysOfWeek ? (
              <div className="space-y-2">
                <p className="text-sm font-medium">{habitsDict.daysOfWeekLabel}</p>
                <div className="flex flex-wrap gap-2">
                  {habitsDict.weekdays.map((label, index) => {
                    const selected = values.daysOfWeek.includes(index);
                    return (
                      <button
                        key={label}
                        type="button"
                        onClick={() => toggleDay(index)}
                        className={`rounded-xl px-3 py-2 text-sm font-medium transition-colors ${selected
                            ? "bg-primary text-primary-foreground"
                            : "bg-accent text-accent-foreground hover:bg-primary/15 hover:text-primary"
                          }`}
                      >
                        {label}
                      </button>
                    );
                  })}
                </div>
              </div>
            ) : null}

            <label className="flex items-center gap-3 rounded-2xl bg-input px-4 py-3 ring-1 ring-border">
              <input
                type="checkbox"
                checked={values.allowMultipleLogsPerDay}
                onChange={(e) => setValues((c) => ({ ...c, allowMultipleLogsPerDay: e.target.checked }))}
                className="size-4 rounded border-border text-primary focus:ring-primary"
              />
              <span className="text-sm">{habitsDict.allowMultipleLogsLabel}</span>
            </label>

            <label className="flex items-center gap-3 rounded-2xl bg-input px-4 py-3 ring-1 ring-border">
              <input
                type="checkbox"
                checked={values.reminder}
                onChange={(e) =>
                  setValues((c) => ({
                    ...c,
                    reminder: e.target.checked,
                    reminderTime: e.target.checked ? c.reminderTime || "09:00" : c.reminderTime,
                  }))
                }
                className="size-4 rounded border-border text-primary focus:ring-primary"
              />
              <span className="text-sm">{habitsDict.reminderLabel}</span>
            </label>

            {values.reminder ? (
              <label className="block space-y-2 text-sm font-semibold text-foreground">
                <span>{habitsDict.reminderTimeLabel}</span>
                <input
                  type="time"
                  value={values.reminderTime}
                  onChange={(e) => setValues((c) => ({ ...c, reminderTime: e.target.value }))}
                  className="h-12 w-full rounded-2xl border border-border bg-input px-4 outline-none focus:border-primary focus:ring-2 focus:ring-primary/20"
                />
                {errors.reminderTime ? (
                  <p className="text-sm text-destructive">{errors.reminderTime}</p>
                ) : null}
              </label>
            ) : null}

            <label className="flex items-center gap-3 rounded-2xl bg-input px-4 py-3 ring-1 ring-border">
              <input
                type="checkbox"
                checked={values.isActive}
                onChange={(e) => setValues((c) => ({ ...c, isActive: e.target.checked }))}
                className="size-4 rounded border-border text-primary focus:ring-primary"
              />
              <span className="text-sm">{habitsDict.isActiveLabel}</span>
            </label>
          </div>

          <div className="shrink-0 border-t border-border bg-card px-6 py-4">
            <div className="flex flex-row gap-3">
              <button
                type="submit"
                disabled={isSubmitting || isDeleting}
                className="inline-flex h-12 flex-1 items-center justify-center rounded-2xl bg-primary text-primary-foreground shadow-soft-sm transition-all hover:brightness-105 disabled:opacity-60"
              >
                {isSubmitting ? habitsDict.saving : habitsDict.save}
              </button>

              <button
                type="button"
                onClick={onClose}
                className="inline-flex h-12 flex-1 items-center justify-center rounded-2xl border border-border bg-background text-foreground transition-colors hover:bg-accent"
              >
                {habitsDict.cancel}
              </button>

              {mode === "edit" && onDelete ? (
                <button
                  type="button"
                  onClick={onDelete}
                  disabled={isDeleting || isSubmitting}
                  className="inline-flex h-12 flex-1 items-center justify-center rounded-2xl border border-destructive/30 text-destructive transition-colors hover:bg-destructive/10 disabled:opacity-60"
                >
                  {habitsDict.delete}
                </button>
              ) : null}
            </div>
          </div>
        </form>
      </div>
    </div>
  );
}
