"use client";

import React, { useState, useEffect, useCallback, useMemo, useRef } from "react";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import * as z from "zod";
import { useSession } from "next-auth/react";
import { toast, Flip } from "react-toastify";
import Cookies from "js-cookie";

import {
  Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage,
} from "@/components/ui/form";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import Loader from "@/components/common/Loader";

const formSchema = z.object({
  name: z.string().min(1, "Name is required").max(50, "Name too long"),
  email: z.string().email("Invalid email address"),
  mobile: z.string().regex(/^[0-9]{11}$/, "Invalid phone number"),
  gender: z.enum(["male", "female", "other"]),
  date_of_birth: z.date().refine((dob) => {
    const today = new Date();
    const minAgeDate = new Date(today.getFullYear() - 13, today.getMonth(), today.getDate());
    return dob <= minAgeDate;
  }, "You must be at least 13 years old"),
  image: z.string().optional(),
});

type FormData = z.infer<typeof formSchema>;

type Profile = {
  full_name: string;
  mobile_number: string;
  picture: { file_url: string };
  gender: string;
  date_of_birth: Date;
  picUrl: string;
};

type Account = {
  id: string;
  userId: number;
  type: string;
  provider: string;
};

type User = {
  email: string;
  profile: Profile;
  account: Account;
};

async function getUserByUuid(uuid: string) {
  const res = await fetch(`/api/user/${uuid}`);
  if (!res.ok) throw new Error("Failed to fetch user");
  return await res.json();
}

async function getProfilePictureUrl() {
  const res = await fetch("/api/user/propic");
  if (!res.ok) throw new Error("Failed to fetch profile picture");
  const data = await res.json();
  if (data.picUrl) Cookies.set("picUrl", data.picUrl, { expires: 1 });
  return data.picUrl;
}

export function ProfileForm() {
  const { data: session } = useSession();
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [user, setUser] = useState<User | null>(null);
  const [avatar, setAvatar] = useState<File | null>(null);
  const [avatarPreview, setAvatarPreview] = useState("/user.png");
  const [isEditMode, setIsEditMode] = useState(false);

  const fileInputRef = useRef<HTMLInputElement | null>(null);
  const avatarUrlRef = useRef<string>("");

  const form = useForm<FormData>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      name: "",
      email: "",
      mobile: "",
      gender: "male",
      date_of_birth: new Date(),
    },
  });

  const userData = useMemo(() => user, [user]);

  const fetchUserData = useCallback(async () => {
    if (!session?.user?.uuid) return;
    try {
      setLoading(true);
      const { User } = await getUserByUuid(session.user.uuid);
      const picUrl = Cookies.get("picUrl") || (await getProfilePictureUrl());
      setUser(User);
      setAvatarPreview(picUrl || "/profile/user.png");
    } catch (err: any) {
      setError(err.message || "Failed to load user data");
      toast.error("Failed to load profile data", {
        position: "bottom-right",
        theme: "colored",
        transition: Flip,
      });
    } finally {
      setLoading(false);
    }
  }, [session]);

  // Handle form population when user is loaded
  useEffect(() => {
    if (user) {
      form.reset({
        name: user.profile.full_name,
        email: user.email,
        mobile: user.profile.mobile_number,
        gender: user.profile.gender?.toLowerCase() as "male" | "female" | "other",
        date_of_birth: new Date(user.profile.date_of_birth),
      });
    }
  }, [user, form]);

  useEffect(() => {
    fetchUserData();
  }, [fetchUserData])

  useEffect(() => {
    avatarUrlRef.current = avatarPreview;
    return () => {
      if (avatarUrlRef.current.startsWith("blob:")) {
        URL.revokeObjectURL(avatarUrlRef.current);
      }
    };
  }, [ avatarPreview]);

  const handleAvatarChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (file) {
      if (file.size > 2 * 1024 * 1024) {
        toast.error("File size exceeds 2MB limit", {
          position: "bottom-right",
          theme: "colored",
          transition: Flip,
        });
        return;
      }
      setAvatar(file);
      setAvatarPreview(URL.createObjectURL(file));
    }
  };

  const onSubmit = async (data: FormData) => {
    if (!session?.user?.uuid) return;
    const formData = new FormData();
    formData.append("name", data.name);
    formData.append("email", data.email);
    formData.append("mobile", data.mobile);
    formData.append("gender", data.gender);
    formData.append("date_of_birth", data.date_of_birth.toISOString());
    formData.append("editedBy", data.name);
    if (avatar) formData.append("profileImage", avatar);

    try {
      const res = await fetch(`/api/user/${session.user.uuid}`, {
        method: "PUT",
        body: formData,
      });

      Cookies.remove("picUrl")

      if (!res.ok) throw new Error("Failed to update profile");
      setIsEditMode(false);
      setUser((prev) => prev && ({
        ...prev,
        email: data.email,
        profile: {
          ...prev.profile,
          full_name: data.name,
          mobile_number: data.mobile,
          gender: data.gender,
          date_of_birth: data.date_of_birth,
        },
      }));
      toast.success("Details Updated!", {
        position: "bottom-right",
        theme: "colored",
        transition: Flip,
      });
    } catch (err) {
      toast.error("Failed to update profile", {
        position: "bottom-right",
        theme: "colored",
        transition: Flip,
      });
    }
  };

  const handleCancelEdit = () => {
    if (!userData) return;
    form.reset({
      name: userData.profile.full_name,
      email: userData.email,
      mobile: userData.profile.mobile_number,
      gender: userData.profile.gender?.toLowerCase() as "male" | "female" | "other",
      date_of_birth: new Date(userData.profile.date_of_birth),
    });
    setAvatar(null);
    setAvatarPreview(Cookies.get("picUrl") || "/user.png");
    setIsEditMode(false);
  };

  if (loading) return <Loader />;
  if (error) return <div className="text-center text-red-500 py-8">{error}</div>;

  return (
    <div className="space-y-6">
      <div className="flex items-center gap-x-3">
        <Avatar className="h-16 w-16">
          <AvatarImage src={avatarPreview} alt={user?.profile.full_name || "User"} />
          <AvatarFallback>
            {user?.profile.full_name?.split(" ").map(n => n[0]).join("")}
          </AvatarFallback>
        </Avatar>
        <div className="flex flex-col">
          {isEditMode ? (
            <>
              <input
                type="file"
                id="avatar"
                accept="image/*"
                onChange={handleAvatarChange}
                className="sr-only"
                ref={fileInputRef}
              />
              <Button size="sm" variant="outline" onClick={() => fileInputRef.current?.click()}>
                Change avatar
              </Button>
              <p className="text-xs text-muted-foreground mt-1">JPG, GIF or PNG. Max size of 2MB</p>
            </>
          ) : (
            <h1 className="text-lg font-medium">Hello, {user?.profile.full_name}</h1>
          )}
        </div>
      </div>

      <Form {...form}>
        <div className="space-y-4">
          <FormField name="name" control={form.control} render={({ field }) => (
            <FormItem>
              <FormLabel>Name</FormLabel>
              <FormControl><Input {...field} disabled={!isEditMode} /></FormControl>
              <FormDescription>This is your public display name.</FormDescription>
              <FormMessage />
            </FormItem>
          )} />

          <FormField name="email" control={form.control} render={({ field }) => (
            <FormItem>
              <FormLabel>Email</FormLabel>
              <FormControl><Input {...field} disabled={!isEditMode} type="email" /></FormControl>
              <FormDescription>Your email address will be used for notifications.</FormDescription>
              <FormMessage />
            </FormItem>
          )} />

          <FormField name="mobile" control={form.control} render={({ field }) => (
            <FormItem>
              <FormLabel>Phone Number</FormLabel>
              <FormControl><Input {...field} disabled={!isEditMode} type="tel" /></FormControl>
              <FormDescription>Your phone number will be used for order updates.</FormDescription>
              <FormMessage />
            </FormItem>
          )} />

          <FormField name="gender" control={form.control} render={({ field }) => (
            <FormItem>
              <FormLabel>Gender</FormLabel>
              <FormControl>
                <RadioGroup onValueChange={field.onChange} value={field.value} className="flex space-x-4" disabled={!isEditMode}>
                  <div className="flex items-center space-x-2">
                    <RadioGroupItem value="male" id="male" />
                    <FormLabel htmlFor="male">Male</FormLabel>
                  </div>
                  <div className="flex items-center space-x-2">
                    <RadioGroupItem value="female" id="female" />
                    <FormLabel htmlFor="female">Female</FormLabel>
                  </div>
                  <div className="flex items-center space-x-2">
                    <RadioGroupItem value="other" id="other" />
                    <FormLabel htmlFor="other">Other</FormLabel>
                  </div>
                </RadioGroup>
              </FormControl>
              <FormMessage />
            </FormItem>
          )} />

          <FormField name="date_of_birth" control={form.control} render={({ field }) => (
            <FormItem>
              <FormLabel>Date of Birth</FormLabel>
              <FormControl>
                <Input
                  type="date"
                  value={field.value.toISOString().split("T")[0]}
                  onChange={e => field.onChange(new Date(e.target.value))}
                  disabled={!isEditMode}
                />
              </FormControl>
              <FormMessage />
            </FormItem>
          )} />

          <div className="flex gap-2">
            {isEditMode ? (
              <>
                <Button type="submit" className="text-white" onClick={form.handleSubmit(onSubmit)}>Update Profile</Button>
                <Button type="button" variant="outline" onClick={handleCancelEdit}>Cancel</Button>
              </>
            ) : (
              <Button type="button" className="text-white" onClick={() => setIsEditMode(true)}>Edit Profile</Button>
            )}
          </div>
        </div>
      </Form>
    </div>
  );
}
