"use client";

import { useMemo, useTransition } from "react";
import { useRouter } from "next/navigation";
import { useSession } from "next-auth/react";
import { useForm, useWatch, Controller } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { Loader2 } from "lucide-react";
import { toast } from "sonner";

import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { FormField } from "@/components/auth/form-field";
import { updateProfileAction } from "@/actions/account-actions";
import { updateProfileSchema, SUPPORTED_LANGUAGES, SUPPORTED_COUNTRIES } from "@/validators/account";
import { useLanguage } from "@/lib/i18n/context";
import type { Locale } from "@/lib/i18n/translations";

const accountFormSchema = updateProfileSchema.extend({
  avatarUrl: z.union([z.literal(""), z.url("Enter a valid image URL")]).optional(),
});
type AccountFormInput = z.infer<typeof accountFormSchema>;

const FALLBACK_TIMEZONES = [
  "UTC",
  "America/Los_Angeles",
  "America/Denver",
  "America/Chicago",
  "America/New_York",
  "America/Mexico_City",
  "America/Bogota",
  "America/Sao_Paulo",
  "Europe/London",
  "Europe/Madrid",
  "Europe/Paris",
  "Europe/Berlin",
  "Asia/Dubai",
  "Asia/Kolkata",
  "Asia/Singapore",
  "Asia/Tokyo",
  "Australia/Sydney",
];

function getTimezones() {
  try {
    const zones =
      typeof Intl.supportedValuesOf === "function"
        ? Intl.supportedValuesOf("timeZone")
        : FALLBACK_TIMEZONES;
    // New users default to "UTC" (see prisma/schema.prisma), but the IANA
    // list Intl reports usually omits it in favor of area/city zones — add
    // it back so that default value actually has a matching option.
    return zones.includes("UTC") ? zones : ["UTC", ...zones];
  } catch {
    return FALLBACK_TIMEZONES;
  }
}

function initials(name?: string | null, email?: string | null) {
  if (name) {
    const parts = name.trim().split(/\s+/);
    return (parts[0]?.[0] ?? "").concat(parts[1]?.[0] ?? "").toUpperCase() || "?";
  }
  return email?.[0]?.toUpperCase() ?? "?";
}

export function AccountForm({
  user,
}: {
  user: {
    firstName: string;
    lastName: string;
    email: string;
    avatarUrl: string | null;
    timezone: string;
    language: "EN" | "ES";
    country: string | null;
  };
}) {
  const router = useRouter();
  const { update: updateSession } = useSession();
  const { t, locale, setLocale } = useLanguage();
  const f = t.app.accountForm;
  const [isPending, startTransition] = useTransition();
  const timezones = useMemo(() => getTimezones(), []);

  const {
    register,
    handleSubmit,
    control,
    formState: { errors },
  } = useForm<AccountFormInput>({
    resolver: zodResolver(accountFormSchema),
    defaultValues: {
      firstName: user.firstName,
      lastName: user.lastName,
      timezone: user.timezone,
      language: user.language,
      country: user.country ?? "",
      avatarUrl: user.avatarUrl ?? "",
    },
  });

  const watchedAvatarUrl = useWatch({ control, name: "avatarUrl" });
  const watchedFirstName = useWatch({ control, name: "firstName" });
  const watchedLastName = useWatch({ control, name: "lastName" });

  function onSubmit(values: AccountFormInput) {
    startTransition(async () => {
      const result = await updateProfileAction(values, locale);
      if (!result.success) {
        toast.error(result.error);
        return;
      }

      await updateSession({
        firstName: values.firstName,
        lastName: values.lastName,
        name: `${values.firstName} ${values.lastName}`.trim(),
        image: values.avatarUrl || null,
        language: values.language,
      });

      // Saved language preference wins immediately — updates context,
      // localStorage, and every consumer of useLanguage() (including this
      // toast, which is why it's sent after this call).
      const newLocale = values.language.toLowerCase() as Locale;
      if (newLocale !== locale) setLocale(newLocale);

      toast.success(f.profileUpdatedToast);
      router.refresh();
    });
  }

  return (
    <form onSubmit={handleSubmit(onSubmit)} noValidate className="flex flex-col gap-5">
      <div className="flex items-center gap-4">
        <Avatar size="lg">
          <AvatarImage src={watchedAvatarUrl || undefined} alt="" />
          <AvatarFallback>
            {initials(`${watchedFirstName} ${watchedLastName}`, user.email)}
          </AvatarFallback>
        </Avatar>
        <div className="flex-1">
          <FormField id="avatarUrl" label={f.avatarUrl} error={errors.avatarUrl?.message}>
            <Input
              id="avatarUrl"
              type="url"
              placeholder="https://…"
              aria-invalid={!!errors.avatarUrl}
              {...register("avatarUrl")}
            />
          </FormField>
        </div>
      </div>

      <div className="grid grid-cols-2 gap-3">
        <FormField id="firstName" label={f.firstName} error={errors.firstName?.message}>
          <Input id="firstName" aria-invalid={!!errors.firstName} {...register("firstName")} />
        </FormField>
        <FormField id="lastName" label={f.lastName} error={errors.lastName?.message}>
          <Input id="lastName" aria-invalid={!!errors.lastName} {...register("lastName")} />
        </FormField>
      </div>

      <FormField id="email" label={f.email}>
        <Input id="email" value={user.email} disabled readOnly />
      </FormField>

      <div className="grid gap-3 sm:grid-cols-2">
        <FormField id="timezone" label={f.timezone} error={errors.timezone?.message}>
          <Controller
            name="timezone"
            control={control}
            render={({ field }) => (
              <Select value={field.value} onValueChange={field.onChange}>
                <SelectTrigger id="timezone" className="w-full">
                  <SelectValue placeholder={f.selectTimezone} />
                </SelectTrigger>
                <SelectContent>
                  {timezones.map((tz) => (
                    <SelectItem key={tz} value={tz}>
                      {tz}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            )}
          />
        </FormField>

        <FormField id="language" label={f.language} error={errors.language?.message}>
          <Controller
            name="language"
            control={control}
            render={({ field }) => (
              <Select value={field.value} onValueChange={field.onChange}>
                <SelectTrigger id="language" className="w-full">
                  <SelectValue placeholder={f.selectLanguage} />
                </SelectTrigger>
                <SelectContent>
                  {SUPPORTED_LANGUAGES.map((lang) => (
                    <SelectItem key={lang.value} value={lang.value}>
                      {lang.label}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            )}
          />
        </FormField>
      </div>

      <FormField id="country" label={f.country} error={errors.country?.message}>
        <Controller
          name="country"
          control={control}
          render={({ field }) => (
            <Select value={field.value || undefined} onValueChange={field.onChange}>
              <SelectTrigger id="country" className="w-full">
                <SelectValue placeholder={f.selectCountry} />
              </SelectTrigger>
              <SelectContent>
                {SUPPORTED_COUNTRIES.map((country) => (
                  <SelectItem key={country.value} value={country.value}>
                    {country.label}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          )}
        />
      </FormField>

      <Button type="submit" size="lg" disabled={isPending} className="mt-2 self-start">
        {isPending ? <Loader2 className="size-4 animate-spin" /> : null}
        {f.saveChanges}
      </Button>
    </form>
  );
}
