import { useState, useEffect } from "react";
import { useQuery, useMutation } from "@tanstack/react-query";
import { Card, CardContent } from "@/components/ui/card";
import { useToast } from "@/hooks/use-toast";
import { apiRequest, queryClient } from "@/lib/queryClient";
import { Calendar } from "@/components/ui/calendar";

const DAYS = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"] as const;
const DAY_LABELS: Record<typeof DAYS[number], string> = {
  monday: "Monday",
  tuesday: "Tuesday",
  wednesday: "Wednesday",
  thursday: "Thursday",
  friday: "Friday",
  saturday: "Saturday",
  sunday: "Sunday",
};

type Day = typeof DAYS[number];

type DayHours = {
  enabled: boolean;
  amStart: string;
  amEnd: string;
  pmStart: string;
  pmEnd: string;
};

type WeekHours = Record<Day, DayHours>;

export type OfficeHoursData = {
  doctors: WeekHours;
  hygienists: WeekHours;
  overrideDates?: string[]; // YYYY-MM-DD dates where office hours are lifted entirely
};

const DEFAULT_DAY_HOURS: DayHours = {
  enabled: true,
  amStart: "09:00",
  amEnd: "12:00",
  pmStart: "13:00",
  pmEnd: "17:00",
};

const WEEKEND_DEFAULT: DayHours = {
  enabled: false,
  amStart: "09:00",
  amEnd: "12:00",
  pmStart: "13:00",
  pmEnd: "17:00",
};

function buildDefaultWeek(): WeekHours {
  return {
    monday: { ...DEFAULT_DAY_HOURS },
    tuesday: { ...DEFAULT_DAY_HOURS },
    wednesday: { ...DEFAULT_DAY_HOURS },
    thursday: { ...DEFAULT_DAY_HOURS },
    friday: { ...DEFAULT_DAY_HOURS },
    saturday: { ...WEEKEND_DEFAULT },
    sunday: { ...WEEKEND_DEFAULT },
  };
}

const DEFAULT_OFFICE_HOURS: OfficeHoursData = {
  doctors: buildDefaultWeek(),
  hygienists: buildDefaultWeek(),
};

function TimeSelect({
  value,
  onChange,
  disabled,
}: {
  value: string;
  onChange: (v: string) => void;
  disabled?: boolean;
}) {
  const options: string[] = [];
  for (let h = 6; h <= 20; h++) {
    options.push(`${String(h).padStart(2, "0")}:00`);
    options.push(`${String(h).padStart(2, "0")}:30`);
  }

  const toDisplay = (t: string) => {
    const parts = t.split(":").map(Number);
    const hh = parts[0] ?? 0;
    const mm = parts[1] ?? 0;
    const period = hh >= 12 ? "PM" : "AM";
    const h12 = hh > 12 ? hh - 12 : hh === 0 ? 12 : hh;
    return `${h12}:${String(mm).padStart(2, "0")} ${period}`;
  };

  return (
    <select
      value={value}
      onChange={(e) => onChange(e.target.value)}
      disabled={disabled}
      className="border rounded px-1 py-0.5 text-sm disabled:opacity-50 disabled:cursor-not-allowed"
    >
      {options.map((o) => (
        <option key={o} value={o}>
          {toDisplay(o)}
        </option>
      ))}
    </select>
  );
}

function DayRow({
  day,
  hours,
  onChange,
}: {
  day: Day;
  hours: DayHours;
  onChange: (updated: DayHours) => void;
}) {
  const set = (field: keyof DayHours, value: string | boolean) =>
    onChange({ ...hours, [field]: value });

  return (
    <div className={`grid grid-cols-[120px_1fr] gap-2 items-start py-2 border-b last:border-b-0 ${!hours.enabled ? "opacity-60" : ""}`}>
      <label className="flex items-center gap-2 cursor-pointer pt-1">
        <input
          type="checkbox"
          checked={hours.enabled}
          onChange={(e) => set("enabled", e.target.checked)}
          className="w-4 h-4 accent-teal-600"
        />
        <span className="text-sm font-medium">{DAY_LABELS[day]}</span>
      </label>

      <div className="flex flex-wrap gap-x-6 gap-y-1">
        <div className="flex items-center gap-1.5 text-sm">
          <span className="text-gray-500 w-6">AM</span>
          <TimeSelect value={hours.amStart} onChange={(v) => set("amStart", v)} disabled={!hours.enabled} />
          <span className="text-gray-400">–</span>
          <TimeSelect value={hours.amEnd} onChange={(v) => set("amEnd", v)} disabled={!hours.enabled} />
        </div>
        <div className="flex items-center gap-1.5 text-sm">
          <span className="text-gray-500 w-6">PM</span>
          <TimeSelect value={hours.pmStart} onChange={(v) => set("pmStart", v)} disabled={!hours.enabled} />
          <span className="text-gray-400">–</span>
          <TimeSelect value={hours.pmEnd} onChange={(v) => set("pmEnd", v)} disabled={!hours.enabled} />
        </div>
      </div>
    </div>
  );
}

function SectionHours({
  title,
  subtitle,
  week,
  onChange,
}: {
  title: string;
  subtitle: string;
  week: WeekHours;
  onChange: (updated: WeekHours) => void;
}) {
  return (
    <div className="border rounded-lg p-4">
      <div className="mb-3">
        <h4 className="font-semibold text-gray-800">{title}</h4>
        <p className="text-xs text-gray-500 mt-0.5">{subtitle}</p>
      </div>
      {DAYS.map((day) => (
        <DayRow
          key={day}
          day={day}
          hours={week[day]}
          onChange={(updated) => onChange({ ...week, [day]: updated })}
        />
      ))}
    </div>
  );
}

function toYMD(date: Date): string {
  return date.toLocaleDateString("en-CA"); // "YYYY-MM-DD" in local time
}

function formatDisplayDate(ymd: string): string {
  // "2026-05-10" → "May 10, 2026"
  const [y, m, d] = ymd.split("-").map(Number);
  return new Date(y!, m! - 1, d!).toLocaleDateString("en-US", {
    month: "short", day: "numeric", year: "numeric",
  });
}

export function OfficeHoursCard() {
  const { toast } = useToast();
  const [formData, setFormData] = useState<OfficeHoursData>(DEFAULT_OFFICE_HOURS);

  // Override-dates UI state (not persisted until Save is clicked)
  const [overrideToggle, setOverrideToggle] = useState(false);
  const [pickedDate, setPickedDate] = useState<Date | undefined>(undefined);

  const { data: savedHours, isLoading } = useQuery<OfficeHoursData | null>({
    queryKey: ["/api/office-hours"],
    queryFn: async () => {
      const res = await apiRequest("GET", "/api/office-hours");
      if (!res.ok) return null;
      return res.json();
    },
  });

  useEffect(() => {
    if (savedHours) {
      setFormData({
        doctors: { ...buildDefaultWeek(), ...savedHours.doctors },
        hygienists: { ...buildDefaultWeek(), ...savedHours.hygienists },
        overrideDates: savedHours.overrideDates ?? [],
      });
    }
  }, [savedHours]);

  const overrideDates: string[] = formData.overrideDates ?? [];

  const addOverrideDate = () => {
    if (!pickedDate) return;
    const ymd = toYMD(pickedDate);
    if (overrideDates.includes(ymd)) return; // already added
    setFormData((prev) => ({ ...prev, overrideDates: [...overrideDates, ymd].sort() }));
    setPickedDate(undefined);
  };

  const removeOverrideDate = (ymd: string) => {
    setFormData((prev) => ({
      ...prev,
      overrideDates: overrideDates.filter((d) => d !== ymd),
    }));
  };

  const saveMutation = useMutation({
    mutationFn: async (data: OfficeHoursData) => {
      const res = await apiRequest("PUT", "/api/office-hours", data);
      if (!res.ok) {
        const err = await res.json().catch(() => null);
        throw new Error(err?.message || "Failed to save office hours");
      }
      return res.json();
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["/api/office-hours"] });
      toast({ title: "Office Hours Saved" });
    },
    onError: (err: any) => {
      toast({ title: "Error", description: err?.message, variant: "destructive" });
    },
  });

  if (isLoading) return <p className="text-sm text-gray-400 py-4">Loading...</p>;

  return (
    <Card>
      <CardContent className="py-6 space-y-6">
        <div>
          <h3 className="text-lg font-semibold">Office Hours</h3>
          <p className="text-sm text-gray-500 mt-1">
            Define which time slots are available for scheduling. Appointments outside these hours
            require a manual override by a dental assistant.
          </p>
        </div>

        <SectionHours
          title="Doctors' Hours"
          subtitle="Applies to schedule columns A, B, C"
          week={formData.doctors}
          onChange={(updated) => setFormData((prev) => ({ ...prev, doctors: updated }))}
        />

        <SectionHours
          title="Hygienists' Hours"
          subtitle="Applies to schedule columns D, E, F"
          week={formData.hygienists}
          onChange={(updated) => setFormData((prev) => ({ ...prev, hygienists: updated }))}
        />

        {/* Override Office Hours section */}
        <div className="border rounded-lg p-4 space-y-4">
          <div className="flex items-center justify-between">
            <div>
              <h4 className="font-semibold text-gray-800">Override Office Hours</h4>
              <p className="text-xs text-gray-500 mt-0.5">
                On selected dates, all time slots are open with no restrictions.
              </p>
            </div>
            {/* Toggle */}
            <button
              type="button"
              onClick={() => setOverrideToggle((v) => !v)}
              className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none ${
                overrideToggle ? "bg-teal-600" : "bg-gray-300"
              }`}
              aria-pressed={overrideToggle}
            >
              <span
                className={`inline-block h-4 w-4 transform rounded-full bg-white shadow transition-transform ${
                  overrideToggle ? "translate-x-6" : "translate-x-1"
                }`}
              />
            </button>
          </div>

          {/* Calendar + add button — shown when toggle is on */}
          {overrideToggle && (
            <div className="space-y-3">
              <p className="text-sm text-gray-600">Select a date to add to the override list:</p>
              <div className="border rounded-md inline-block">
                <Calendar
                  mode="single"
                  selected={pickedDate}
                  onSelect={(d) => setPickedDate(d ?? undefined)}
                  className="p-2"
                />
              </div>
              <div>
                <button
                  type="button"
                  onClick={addOverrideDate}
                  disabled={!pickedDate}
                  className="px-3 py-1.5 text-sm bg-teal-600 text-white rounded hover:bg-teal-700 disabled:opacity-40"
                >
                  Add Date
                </button>
              </div>
            </div>
          )}

          {/* List of saved override dates */}
          {overrideDates.length > 0 && (
            <div className="space-y-1">
              <p className="text-xs font-medium text-gray-500 uppercase tracking-wide">Override dates</p>
              <ul className="space-y-1">
                {overrideDates.map((ymd) => (
                  <li key={ymd} className="flex items-center justify-between text-sm bg-teal-50 border border-teal-100 rounded px-3 py-1.5">
                    <span className="font-medium text-teal-800">{formatDisplayDate(ymd)}</span>
                    <button
                      type="button"
                      onClick={() => removeOverrideDate(ymd)}
                      className="text-teal-400 hover:text-red-500 text-xs ml-4"
                      title="Remove"
                    >
                      ✕
                    </button>
                  </li>
                ))}
              </ul>
            </div>
          )}
        </div>

        <div className="pt-2">
          <button
            onClick={() => saveMutation.mutate(formData)}
            disabled={saveMutation.isPending}
            className="bg-teal-600 text-white px-4 py-2 rounded hover:bg-teal-700 text-sm disabled:opacity-50"
          >
            {saveMutation.isPending ? "Saving..." : "Save Office Hours"}
          </button>
        </div>
      </CardContent>
    </Card>
  );
}
