import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { format } from "date-fns";
import { apiRequest } from "@/lib/queryClient";
import { Button } from "@/components/ui/button";
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Calendar } from "@/components/ui/calendar";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";
import { CalendarIcon, Clock } from "lucide-react";
import { cn } from "@/lib/utils";
import { useQuery } from "@tanstack/react-query";
import { useAuth } from "@/hooks/use-auth";

import {
  AppointmentUncheckedCreateInputObjectSchema,
  PatientUncheckedCreateInputObjectSchema,
  StaffUncheckedCreateInputObjectSchema,
} from "@repo/db/shared/schemas";

import { z } from "zod";
type Appointment = z.infer<typeof AppointmentUncheckedCreateInputObjectSchema>;
type Staff = z.infer<typeof StaffUncheckedCreateInputObjectSchema>;

const insertAppointmentSchema = (
  AppointmentUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
).omit({
  id: true,
  createdAt: true,
  userId: true,
});
type InsertAppointment = z.infer<typeof insertAppointmentSchema>;

const updateAppointmentSchema = (
  AppointmentUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
)
  .omit({
    id: true,
    createdAt: true,
    userId: true,
  })
  .partial();
type UpdateAppointment = z.infer<typeof updateAppointmentSchema>;

const PatientSchema = (
  PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
).omit({
  appointments: true,
});
type Patient = z.infer<typeof PatientSchema>;

interface AppointmentFormProps {
  appointment?: Appointment;
  patients: Patient[];
  onSubmit: (data: InsertAppointment | UpdateAppointment) => void;
  isLoading?: boolean;
}

export function AppointmentForm({
  appointment,
  patients,
  onSubmit,
  isLoading = false,
}: AppointmentFormProps) {
  const { user } = useAuth();

  const { data: staffMembersRaw = [] as Staff[], isLoading: isLoadingStaff } =
    useQuery<Staff[]>({
      queryKey: ["/api/staffs/"],
      queryFn: async () => {
        const res = await apiRequest("GET", "/api/staffs/");
        return res.json();
      },
      enabled: !!user,
    });

  const colorMap: Record<string, string> = {
    "Dr. Kai Gao": "bg-blue-600",
    "Dr. Jane Smith": "bg-emerald-600",
  };

  const staffMembers = staffMembersRaw.map((staff) => ({
    ...staff,
    color: colorMap[staff.name] || "bg-gray-400",
  }));

  // Get the stored data from session storage
  const storedDataString = sessionStorage.getItem("newAppointmentData");
  let parsedStoredData = null;

  // Try to parse it if it exists
  if (storedDataString) {
    try {
      parsedStoredData = JSON.parse(storedDataString);
    } catch (error) {
      console.error("Error parsing stored appointment data:", error);
    }
  }

  // Format the date and times for the form
  const defaultValues: Partial<Appointment> = appointment
    ? {
        patientId: appointment.patientId,
        title: appointment.title,
        date: new Date(appointment.date),
        startTime: appointment.startTime || "09:00", // Default "09:00"
        endTime: appointment.endTime || "09:30", // Default "09:30"
        type: appointment.type,
        notes: appointment.notes || "",
        status: appointment.status || "scheduled",
        staffId:
          typeof appointment.staffId === "number"
            ? appointment.staffId
            : undefined,
      }
    : parsedStoredData
      ? {
          patientId: Number(parsedStoredData.patientId),
          date: new Date(parsedStoredData.date),
          title: parsedStoredData.title || "",
          startTime: parsedStoredData.startTime,
          endTime: parsedStoredData.endTime,
          type: parsedStoredData.type || "checkup",
          status: parsedStoredData.status || "scheduled",
          notes: parsedStoredData.notes || "",
          staffId:
            typeof parsedStoredData.staff === "number"
              ? parsedStoredData.staff
              : (staffMembers?.[0]?.id ?? undefined),
        }
      : {
          date: new Date(),
          title: "",
          startTime: "09:00",
          endTime: "09:30",
          type: "checkup",
          status: "scheduled",
          staffId: staffMembers?.[0]?.id ?? undefined,
        };

  const form = useForm<InsertAppointment>({
    resolver: zodResolver(insertAppointmentSchema),
    defaultValues,
  });

  // Force form field values to update and clean up storage
  useEffect(() => {
    if (parsedStoredData) {
      // Update form field values directly
      if (parsedStoredData.startTime) {
        form.setValue("startTime", parsedStoredData.startTime);
      }

      if (parsedStoredData.endTime) {
        form.setValue("endTime", parsedStoredData.endTime);
      }

      if (parsedStoredData.staff) {
        form.setValue("staffId", parsedStoredData.staff);
      }

      if (parsedStoredData.date) {
        form.setValue("date", new Date(parsedStoredData.date));
      }

      // Clean up session storage
      sessionStorage.removeItem("newAppointmentData");
    }
  }, [form]);

  const handleSubmit = (data: InsertAppointment) => {
    // Make sure patientId is a number
    const patientId =
      typeof data.patientId === "string"
        ? parseInt(data.patientId, 10)
        : data.patientId;

    // Get patient name for the title
    const patient = patients.find((p) => p.id === patientId);
    const patientName = patient
      ? `${patient.firstName} ${patient.lastName}`
      : "Patient";

    // Auto-create title if it's empty
    let title = data.title;
    if (!title || title.trim() === "") {
      // Format: "April 19" - just the date
      title = format(data.date, "MMMM d");
    }

    let notes = data.notes || "";

    const selectedStaff =
      staffMembers.find((staff) => staff.id?.toString() === data.staffId) ||
      staffMembers[0];

    if (!selectedStaff) {
      console.error("No staff selected and no available staff in the list");
      return; // Handle this case as well
    }

    // If there's no staff information in the notes, add it
    if (!notes.includes("Appointment with")) {
      notes = notes
        ? `${notes}\nAppointment with ${selectedStaff?.name}`
        : `Appointment with ${selectedStaff?.name}`;
    }

    // 👇 Use current date if none provided
    const appointmentDate = data.date ? new Date(data.date) : new Date();

    if (isNaN(appointmentDate.getTime())) {
      console.error("Invalid date:", data.date);
      return;
    }

    onSubmit({
      ...data,
      title,
      notes,
      patientId,
      date: format(appointmentDate, "yyyy-MM-dd"),
      startTime: data.startTime,
      endTime: data.endTime,
    });
  };

  return (
    <div className="form-container">
      <Form {...form}>
        <form
          onSubmit={form.handleSubmit(
            (data) => {
              handleSubmit(data);
            },
            (errors) => {
              console.error("Validation failed:", errors);
            }
          )}
          className="space-y-6"
        >
          <FormField
            control={form.control}
            name="patientId"
            render={({ field }) => (
              <FormItem>
                <FormLabel>Patient</FormLabel>
                <Select
                  disabled={isLoading}
                  onValueChange={(val) => field.onChange(Number(val))}
                  value={field.value?.toString()}
                  defaultValue={field.value?.toString()}
                >
                  <FormControl>
                    <SelectTrigger>
                      <SelectValue placeholder="Select a patient" />
                    </SelectTrigger>
                  </FormControl>
                  <SelectContent>
                    {patients.map((patient) => (
                      <SelectItem
                        key={patient.id}
                        value={patient.id.toString()}
                      >
                        {patient.firstName} {patient.lastName}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
                <FormMessage />
              </FormItem>
            )}
          />

          <FormField
            control={form.control}
            name="title"
            render={({ field }) => (
              <FormItem>
                <FormLabel>
                  Appointment Title{" "}
                  <span className="text-muted-foreground text-xs">
                    (optional)
                  </span>
                </FormLabel>
                <FormControl>
                  <Input
                    placeholder="Leave blank to auto-fill with date"
                    {...field}
                    disabled={isLoading}
                  />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />

          <FormField
            control={form.control}
            name="date"
            render={({ field }) => (
              <FormItem className="flex flex-col">
                <FormLabel>Date</FormLabel>
                <Popover>
                  <PopoverTrigger asChild>
                    <FormControl>
                      <Button
                        variant={"outline"}
                        className={cn(
                          "w-full pl-3 text-left font-normal",
                          !field.value && "text-muted-foreground"
                        )}
                        disabled={isLoading}
                      >
                        {field.value ? (
                          format(field.value, "PPP")
                        ) : (
                          <span>Pick a date</span>
                        )}
                        <CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
                      </Button>
                    </FormControl>
                  </PopoverTrigger>
                  <PopoverContent className="w-auto p-0" align="start">
                    <Calendar
                      mode="single"
                      selected={field.value ? new Date(field.value) : undefined}
                      onSelect={field.onChange}
                      disabled={(date) =>
                        date < new Date(new Date().setHours(0, 0, 0, 0))
                      }
                      initialFocus
                    />
                  </PopoverContent>
                </Popover>
                <FormMessage />
              </FormItem>
            )}
          />

          <div className="grid grid-cols-2 gap-4">
            <FormField
              control={form.control}
              name="startTime"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Start Time</FormLabel>
                  <FormControl>
                    <div className="relative">
                      <Clock className="absolute left-3 top-3 h-4 w-4 text-muted-foreground" />
                      <Input
                        placeholder="09:00"
                        {...field}
                        disabled={isLoading}
                        className="pl-10"
                        value={
                          typeof field.value === "string" ? field.value : ""
                        }
                      />
                    </div>
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />

            <FormField
              control={form.control}
              name="endTime"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>End Time</FormLabel>
                  <FormControl>
                    <div className="relative">
                      <Clock className="absolute left-3 top-3 h-4 w-4 text-muted-foreground" />
                      <Input
                        placeholder="09:30"
                        {...field}
                        disabled={isLoading}
                        className="pl-10"
                        value={
                          typeof field.value === "string" ? field.value : ""
                        }
                      />
                    </div>
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />
          </div>

          <FormField
            control={form.control}
            name="type"
            render={({ field }) => (
              <FormItem>
                <FormLabel>Appointment Type</FormLabel>
                <Select
                  disabled={isLoading}
                  onValueChange={field.onChange}
                  value={field.value}
                  defaultValue={field.value}
                >
                  <FormControl>
                    <SelectTrigger>
                      <SelectValue placeholder="Select a type" />
                    </SelectTrigger>
                  </FormControl>
                  <SelectContent>
                    <SelectItem value="checkup">Checkup</SelectItem>
                    <SelectItem value="cleaning">Cleaning</SelectItem>
                    <SelectItem value="filling">Filling</SelectItem>
                    <SelectItem value="extraction">Extraction</SelectItem>
                    <SelectItem value="root-canal">Root Canal</SelectItem>
                    <SelectItem value="crown">Crown</SelectItem>
                    <SelectItem value="dentures">Dentures</SelectItem>
                    <SelectItem value="consultation">Consultation</SelectItem>
                    <SelectItem value="emergency">Emergency</SelectItem>
                    <SelectItem value="other">Other</SelectItem>
                  </SelectContent>
                </Select>
                <FormMessage />
              </FormItem>
            )}
          />

          <FormField
            control={form.control}
            name="status"
            render={({ field }) => (
              <FormItem>
                <FormLabel>Status</FormLabel>
                <Select
                  disabled={isLoading}
                  onValueChange={field.onChange}
                  value={field.value}
                  defaultValue={field.value}
                >
                  <FormControl>
                    <SelectTrigger>
                      <SelectValue placeholder="Select a status" />
                    </SelectTrigger>
                  </FormControl>
                  <SelectContent>
                    <SelectItem value="scheduled">Scheduled</SelectItem>
                    <SelectItem value="confirmed">Confirmed</SelectItem>
                    <SelectItem value="completed">Completed</SelectItem>
                    <SelectItem value="cancelled">Cancelled</SelectItem>
                    <SelectItem value="no-show">No Show</SelectItem>
                  </SelectContent>
                </Select>
                <FormMessage />
              </FormItem>
            )}
          />

          <FormField
            control={form.control}
            name="staffId"
            render={({ field }) => (
              <FormItem>
                <FormLabel>Doctor/Hygienist</FormLabel>
                <Select
                  disabled={isLoading}
                  onValueChange={(val) => field.onChange(Number(val))}
                  value={field.value ? String(field.value) : undefined}
                  defaultValue={field.value ? String(field.value) : undefined}
                >
                  <FormControl>
                    <SelectTrigger>
                      <SelectValue placeholder="Select staff member" />
                    </SelectTrigger>
                  </FormControl>
                  <SelectContent>
                    {staffMembers.map((staff) => (
                      <SelectItem
                        key={staff.id}
                        value={staff.id?.toString() || ""}
                      >
                        {staff.name} ({staff.role})
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
                <FormMessage />
              </FormItem>
            )}
          />

          <FormField
            control={form.control}
            name="notes"
            render={({ field }) => (
              <FormItem>
                <FormLabel>Notes</FormLabel>
                <FormControl>
                  <Textarea
                    placeholder="Enter any notes about the appointment"
                    {...field}
                    disabled={isLoading}
                    className="min-h-24"
                    value={field.value ?? ""}
                  />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />

          <Button type="submit" disabled={isLoading} className="w-full">
            {appointment ? "Update Appointment" : "Create Appointment"}
          </Button>
        </form>
      </Form>
    </div>
  );
}
