import { useState } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { Badge } from "@/components/ui/badge";
import { Calendar } from "@/components/ui/calendar";
import { toast } from "sonner";
import { Plus, Trash2, CalendarX, CalendarCheck, CalendarDays } from "lucide-react";
import { useBankHolidays } from "@/hooks/useBankHolidays";
import { format } from "date-fns";

const csrfToken = () =>
  (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement | null)?.content ?? "";

const WEEKDAYS = [
  { idx: 1, name: "Monday" },
  { idx: 2, name: "Tuesday" },
  { idx: 3, name: "Wednesday" },
  { idx: 4, name: "Thursday" },
  { idx: 5, name: "Friday" },
  { idx: 6, name: "Saturday" },
  { idx: 0, name: "Sunday" },
];

interface TrainerAvailabilityPanelProps {
  trainerId: string;
  trainerName: string;
}

const TrainerAvailabilityPanel = ({ trainerId, trainerName }: TrainerAvailabilityPanelProps) => {
  const queryClient = useQueryClient();
  const [overrideDate, setOverrideDate] = useState("");
  const [overrideReason, setOverrideReason] = useState("");
  const [pendingDates, setPendingDates] = useState<Date[]>([]);
  const { data: bankHolidays = [] } = useBankHolidays();

  // Fetch trainer to get availability_mode
  const { data: trainer } = useQuery({
    queryKey: ["trainer_detail", trainerId],
    queryFn: async (): Promise<any> => {
      const res = await fetch(`/api/admin/trainers/${trainerId}`);
      if (!res.ok) return null;
      return res.json();
    },
  });

  const mode = (trainer as any)?.availability_mode || "weekly";

  const toggleModeMutation = useMutation({
    mutationFn: async (newMode: string) => {
      const res = await fetch(`/api/admin/trainers/${trainerId}`, {
        method: "PUT",
        headers: { "Content-Type": "application/json", "X-CSRF-TOKEN": csrfToken() },
        body: JSON.stringify({ availability_mode: newMode }),
      });
      if (!res.ok) throw new Error("Failed to update mode");
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["trainer_detail", trainerId] });
      toast.success("Availability mode updated");
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const { data: weeklyAvailability } = useQuery({
    queryKey: ["weekly_availability", trainerId],
    queryFn: async (): Promise<any[]> => {
      const res = await fetch(`/api/admin/trainers/${trainerId}/availability/weekly`);
      if (!res.ok) return [];
      return res.json();
    },
  });

  // Exclusion overrides (non-working days)
  const { data: overrides } = useQuery({
    queryKey: ["availability_overrides", trainerId],
    queryFn: async (): Promise<any[]> => {
      const res = await fetch(`/api/admin/trainers/${trainerId}/availability/overrides?available=false`);
      if (!res.ok) return [];
      return res.json();
    },
  });

  // Specific available dates (for specific_dates mode)
  const { data: specificDates } = useQuery({
    queryKey: ["specific_available_dates", trainerId],
    queryFn: async (): Promise<any[]> => {
      const res = await fetch(`/api/admin/trainers/${trainerId}/availability/overrides?available=true`);
      if (!res.ok) return [];
      return res.json();
    },
  });

  const toggleWeeklyMutation = useMutation({
    mutationFn: async ({ dayOfWeek, isAvailable }: { dayOfWeek: number; isAvailable: boolean }) => {
      const existing = weeklyAvailability?.find((w: any) => w.day_of_week === dayOfWeek);
      if (existing) {
        const res = await fetch(`/api/admin/trainers/${trainerId}/availability/weekly/${existing.id}`, {
          method: "PUT",
          headers: { "Content-Type": "application/json", "X-CSRF-TOKEN": csrfToken() },
          body: JSON.stringify({ is_available: isAvailable }),
        });
        if (!res.ok) throw new Error("Failed to update weekly availability");
      } else {
        const res = await fetch(`/api/admin/trainers/${trainerId}/availability/weekly`, {
          method: "POST",
          headers: { "Content-Type": "application/json", "X-CSRF-TOKEN": csrfToken() },
          body: JSON.stringify({ trainer_id: trainerId, day_of_week: dayOfWeek, is_available: isAvailable }),
        });
        if (!res.ok) throw new Error("Failed to create weekly availability");
      }
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["weekly_availability", trainerId] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const addOverrideMutation = useMutation({
    mutationFn: async () => {
      if (!overrideDate) throw new Error("Date is required");
      const res = await fetch(`/api/admin/trainers/${trainerId}/availability/overrides`, {
        method: "POST",
        headers: { "Content-Type": "application/json", "X-CSRF-TOKEN": csrfToken() },
        body: JSON.stringify({
          trainer_id: trainerId,
          override_date: overrideDate,
          is_available: false,
          reason: overrideReason || null,
        }),
      });
      if (!res.ok) throw new Error("Failed to add non-working day");
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["availability_overrides", trainerId] });
      toast.success("Non-working day added");
      setOverrideDate("");
      setOverrideReason("");
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const bulkAddDatesMutation = useMutation({
    mutationFn: async (dates: Date[]) => {
      if (dates.length === 0) throw new Error("No dates selected");
      const existingSet = new Set(specificDates?.map((d: any) => d.override_date) || []);
      const newDates = dates
        .map((d) => format(d, "yyyy-MM-dd"))
        .filter((d) => !existingSet.has(d));
      if (newDates.length === 0) { toast.info("All selected dates are already added"); return; }
      const rows = newDates.map((d) => ({
        trainer_id: trainerId,
        override_date: d,
        is_available: true,
        reason: "Specific available date",
      }));
      const res = await fetch(`/api/admin/trainers/${trainerId}/availability/overrides/bulk`, {
        method: "POST",
        headers: { "Content-Type": "application/json", "X-CSRF-TOKEN": csrfToken() },
        body: JSON.stringify({ rows }),
      });
      if (!res.ok) throw new Error("Failed to add dates");
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["specific_available_dates", trainerId] });
      toast.success(`${pendingDates.length} date(s) added`);
      setPendingDates([]);
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const deleteOverrideMutation = useMutation({
    mutationFn: async (id: string) => {
      const res = await fetch(`/api/admin/trainers/${trainerId}/availability/overrides/${id}`, {
        method: "DELETE",
        headers: { "X-CSRF-TOKEN": csrfToken() },
      });
      if (!res.ok) throw new Error("Failed to delete override");
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["availability_overrides", trainerId] });
      queryClient.invalidateQueries({ queryKey: ["specific_available_dates", trainerId] });
      toast.success("Day removed");
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const getDayAvailability = (dayOfWeek: number) => {
    const entry = weeklyAvailability?.find((w: any) => w.day_of_week === dayOfWeek);
    return entry?.is_available ?? (dayOfWeek >= 1 && dayOfWeek <= 5);
  };

  const today = new Date().toISOString().split("T")[0];
  const upcomingHolidays = bankHolidays.filter((h) => h.date >= today);
  const upcomingSpecificDates = specificDates?.filter((d: any) => d.override_date >= today) || [];

  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between">
        <h3 className="text-lg font-bold text-foreground">
          Availability — {trainerName}
        </h3>
        <div className="flex items-center gap-2">
          <Button
            variant={mode === "weekly" ? "default" : "outline"}
            size="sm"
            className="text-xs"
            onClick={() => mode !== "weekly" && toggleModeMutation.mutate("weekly")}
          >
            <CalendarDays className="h-3.5 w-3.5 mr-1" />
            Weekly Schedule
          </Button>
          <Button
            variant={mode === "specific_dates" ? "default" : "outline"}
            size="sm"
            className="text-xs"
            onClick={() => mode !== "specific_dates" && toggleModeMutation.mutate("specific_dates")}
          >
            <CalendarCheck className="h-3.5 w-3.5 mr-1" />
            Specific Dates
          </Button>
        </div>
      </div>

      {mode === "weekly" ? (
        <>
          {/* Weekly schedule mode (existing) */}
          <div className="bg-card border border-border rounded-xl p-6">
            <h4 className="font-semibold text-foreground mb-1">Manage Working Days</h4>
            <p className="text-sm text-muted-foreground mb-4">Weekly Working Days</p>

            <div className="grid grid-cols-2 sm:grid-cols-4 gap-4 mb-4">
              {WEEKDAYS.map((day) => (
                <div key={day.idx} className="flex items-center gap-2">
                  <Switch
                    checked={getDayAvailability(day.idx)}
                    onCheckedChange={(checked) => toggleWeeklyMutation.mutate({ dayOfWeek: day.idx, isAvailable: checked })}
                  />
                  <span className="text-sm text-foreground">{day.name}</span>
                </div>
              ))}
            </div>
          </div>

          {/* Bank Holidays + Non-working Days */}
          <div className="grid lg:grid-cols-2 gap-6">
            <div className="bg-card border border-border rounded-xl p-6">
              <h4 className="font-semibold text-foreground mb-4">Bank Holidays</h4>
              <div className="space-y-2 max-h-[300px] overflow-y-auto">
                {upcomingHolidays.map((h) => (
                  <div key={h.date} className="flex items-center gap-2 text-sm text-foreground">
                    <CalendarDays className="h-3.5 w-3.5 text-primary shrink-0" />
                    <span>{h.date} - {h.name}</span>
                  </div>
                ))}
              </div>
            </div>

            <div className="bg-card border border-border rounded-xl p-6">
              <h4 className="font-semibold text-foreground mb-4">Additional Non-working Days</h4>

              <div className="grid grid-cols-[1fr_1fr_auto] gap-2 mb-3 items-end">
                <div className="space-y-1">
                  <Label className="text-xs text-muted-foreground">Date</Label>
                  <Input type="date" value={overrideDate} onChange={(e) => setOverrideDate(e.target.value)} />
                </div>
                <div className="space-y-1">
                  <Label className="text-xs text-muted-foreground">Reason (optional)</Label>
                  <Input value={overrideReason} onChange={(e) => setOverrideReason(e.target.value)} placeholder="e.g., Annual leave" />
                </div>
                <Button variant="hero" size="sm" onClick={() => addOverrideMutation.mutate()} disabled={!overrideDate || addOverrideMutation.isPending}>
                  <Plus className="h-3 w-3 mr-1" /> Add Day
                </Button>
              </div>

              {overrides && overrides.filter((o: any) => o.override_date >= today).length > 0 && (
                <div className="border-t border-border pt-3 space-y-2 max-h-[250px] overflow-y-auto">
                  {overrides
                    .filter((o: any) => o.override_date >= today)
                    .map((o: any) => (
                    <div key={o.id} className="flex items-center justify-between text-sm">
                      <div className="flex items-center gap-2 text-foreground">
                        <CalendarX className="h-3.5 w-3.5 text-destructive shrink-0" />
                        <span>{o.override_date} - {o.reason || "No reason"}</span>
                      </div>
                      <Button variant="ghost" size="icon" className="h-7 w-7 text-destructive" onClick={() => deleteOverrideMutation.mutate(o.id)}>
                        <Trash2 className="h-3 w-3" />
                      </Button>
                    </div>
                  ))}
                </div>
              )}
            </div>
          </div>
        </>
      ) : (
        <>
          {/* Specific Dates mode with calendar */}
          <div className="bg-card border border-border rounded-xl p-6">
            <h4 className="font-semibold text-foreground mb-1">Specific Available Dates</h4>
            <p className="text-sm text-muted-foreground mb-4">
              Click dates on the calendar to select them, then press "Save Selected Dates".
            </p>

            <div className="grid lg:grid-cols-[auto_1fr] gap-6">
              <div>
                <Calendar
                  mode="multiple"
                  selected={pendingDates}
                  onSelect={(dates) => setPendingDates(dates || [])}
                  disabled={(date) => date < new Date(today)}
                  modifiers={{
                    alreadySaved: (specificDates || []).map((d: any) => new Date(d.override_date + "T00:00:00")),
                  }}
                  modifiersClassNames={{
                    alreadySaved: "bg-primary/20 text-primary font-semibold",
                  }}
                  className="p-3 pointer-events-auto rounded-xl border border-border"
                />
                <div className="flex items-center gap-3 mt-3">
                  <Button
                    variant="hero"
                    size="sm"
                    onClick={() => bulkAddDatesMutation.mutate(pendingDates)}
                    disabled={pendingDates.length === 0 || bulkAddDatesMutation.isPending}
                  >
                    <Plus className="h-3 w-3 mr-1" />
                    Save {pendingDates.length} Date{pendingDates.length !== 1 ? "s" : ""}
                  </Button>
                  {pendingDates.length > 0 && (
                    <Button variant="outline" size="sm" onClick={() => setPendingDates([])}>
                      Clear
                    </Button>
                  )}
                </div>
              </div>

              <div>
                <h4 className="font-semibold text-foreground mb-3">
                  Saved Dates
                  <Badge variant="secondary" className="text-xs ml-2">{upcomingSpecificDates.length}</Badge>
                </h4>
                {upcomingSpecificDates.length === 0 ? (
                  <p className="text-sm text-muted-foreground italic">No dates set yet.</p>
                ) : (
                  <div className="grid grid-cols-1 sm:grid-cols-2 gap-2 max-h-[300px] overflow-y-auto">
                    {upcomingSpecificDates.map((d: any) => (
                      <div key={d.id} className="flex items-center justify-between bg-muted/50 rounded-lg px-3 py-2">
                        <div className="flex items-center gap-2 text-sm text-foreground">
                          <CalendarCheck className="h-3.5 w-3.5 text-primary shrink-0" />
                          <span>{new Date(d.override_date + "T00:00:00").toLocaleDateString("en-GB", { weekday: "short", day: "numeric", month: "short", year: "numeric" })}</span>
                        </div>
                        <Button variant="ghost" size="icon" className="h-7 w-7 text-destructive" onClick={() => deleteOverrideMutation.mutate(d.id)}>
                          <Trash2 className="h-3 w-3" />
                        </Button>
                      </div>
                    ))}
                  </div>
                )}
              </div>
            </div>
          </div>
        </>
      )}
    </div>
  );
};

export default TrainerAvailabilityPanel;
