import { useEffect, useRef } from 'react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import {
  updateProfileSchema,
  type UpdateProfileInput,
  type Profile,
} from '@family-wishlist/shared';
import { toast } from 'sonner';
import { Gift, Loader2, Upload } from 'lucide-react';
import { Button } from '@/components/ui/Button';
import { Input } from '@/components/ui/Input';
import { Label } from '@/components/ui/Label';
import { Textarea } from '@/components/ui/Textarea';
import { api, ApiError } from '@/lib/api';
import { useAuthStore } from '@/features/auth/authStore';
import { translateValidation, useI18n } from '@/i18n/i18n';

const MAX_AVATAR_BYTES = 2 * 1024 * 1024;
const AVATAR_MIME_TYPES = new Set(['image/jpeg', 'image/png', 'image/webp', 'image/gif']);

export function ProfileSettingsPage() {
  const { t } = useI18n();
  const refresh = useAuthStore((s) => s.refresh);
  const queryClient = useQueryClient();
  const fileInputRef = useRef<HTMLInputElement>(null);

  const { data, isLoading } = useQuery({
    queryKey: ['profile'],
    queryFn: () => api.get<Profile>('/api/profile'),
  });

  const {
    register,
    handleSubmit,
    reset,
    watch,
    formState: { errors, isSubmitting, isDirty },
  } = useForm<UpdateProfileInput>({
    resolver: zodResolver(updateProfileSchema),
    defaultValues: { slug: '', displayName: '', bio: '', avatarUrl: '' },
  });

  useEffect(() => {
    if (data) {
      reset({
        slug: data.slug,
        displayName: data.displayName,
        bio: data.bio ?? '',
        avatarUrl: data.avatarUrl ?? '',
      });
    }
  }, [data, reset]);

  const update = useMutation({
    mutationFn: (values: UpdateProfileInput) =>
      api.patch<Profile, UpdateProfileInput>('/api/profile', values),
    onSuccess: (p) => {
      toast.success(t('profile.saved'));
      void queryClient.invalidateQueries({ queryKey: ['profile'] });
      void refresh();
      reset({
        slug: p.slug,
        displayName: p.displayName,
        bio: p.bio ?? '',
        avatarUrl: p.avatarUrl ?? '',
      });
    },
    onError: (err) => {
      if (err instanceof ApiError) toast.error(err.message);
      else toast.error(t('profile.saveFailed'));
    },
  });

  const uploadAvatar = useMutation({
    mutationFn: (file: File) => {
      const form = new FormData();
      form.append('file', file);
      return api.upload<Profile>('/api/profile/avatar', form);
    },
    onSuccess: (p) => {
      toast.success(t('profile.avatarUploaded'));
      void queryClient.invalidateQueries({ queryKey: ['profile'] });
      void refresh();
      reset({
        slug: p.slug,
        displayName: p.displayName,
        bio: p.bio ?? '',
        avatarUrl: p.avatarUrl ?? '',
      });
    },
    onError: (err) => {
      if (err instanceof ApiError) toast.error(err.message);
      else toast.error(t('profile.saveFailed'));
    },
  });

  function handleAvatarFile(file: File | undefined): void {
    if (!file) return;
    if (!AVATAR_MIME_TYPES.has(file.type)) {
      toast.error(t('profile.avatarUnsupported'));
      return;
    }
    if (file.size > MAX_AVATAR_BYTES) {
      toast.error(t('profile.avatarTooLarge'));
      return;
    }
    uploadAvatar.mutate(file);
  }

  const submit = handleSubmit((values) => {
    const payload: UpdateProfileInput = {
      ...values,
      bio: values.bio ? values.bio : null,
      avatarUrl: values.avatarUrl ? values.avatarUrl : null,
    };
    update.mutate(payload);
  });

  const avatarPreview = watch('avatarUrl') || data?.avatarUrl;

  return (
    <div className="grid max-w-2xl gap-6">
      <section className="page-section">
        <h1 className="page-section__title">{t('profile.title')}</h1>
        <p className="page-section__text">
          {t('profile.publicPage')}
          <code className="rounded bg-ink/5 px-1.5 py-0.5">/u/{data?.slug ?? '...'}</code>.
        </p>
      </section>

      {isLoading ? (
        <div className="text-muted">{t('common.loading')}</div>
      ) : (
        <form className="profile-form" onSubmit={submit}>
          <section className="profile-form__avatar-panel">
            <span className="profile-form__avatar-preview">
              {avatarPreview ? (
                <img src={avatarPreview} alt="" className="profile-form__avatar-image" />
              ) : (
                <Gift className="h-6 w-6" />
              )}
            </span>
            <div className="profile-form__avatar-copy">
              <h2 className="profile-form__avatar-title">{t('profile.avatar')}</h2>
              <p className="profile-form__avatar-hint">{t('profile.avatarHint')}</p>
            </div>
            <input
              ref={fileInputRef}
              type="file"
              accept="image/jpeg,image/png,image/webp,image/gif"
              className="hidden"
              onChange={(e) => {
                handleAvatarFile(e.target.files?.[0]);
                e.currentTarget.value = '';
              }}
            />
            <Button
              type="button"
              variant="secondary"
              onClick={() => fileInputRef.current?.click()}
              disabled={uploadAvatar.isPending}
            >
              {uploadAvatar.isPending ? (
                <Loader2 className="h-4 w-4 animate-spin" />
              ) : (
                <Upload className="h-4 w-4" />
              )}
              {t('profile.uploadAvatar')}
            </Button>
          </section>
          <div className="field">
            <Label htmlFor="slug">{t('profile.slug')}</Label>
            <Input id="slug" {...register('slug')} />
            {errors.slug && (
              <span className="field__error">{translateValidation(t, errors.slug.message)}</span>
            )}
          </div>
          <div className="field">
            <Label htmlFor="displayName">{t('profile.displayName')}</Label>
            <Input id="displayName" {...register('displayName')} />
            {errors.displayName && (
              <span className="field__error">
                {translateValidation(t, errors.displayName.message)}
              </span>
            )}
          </div>
          <div className="field">
            <Label htmlFor="bio">{t('profile.bio')}</Label>
            <Textarea id="bio" rows={3} {...register('bio')} />
          </div>
          <div className="field">
            <Label htmlFor="avatarUrl">{t('profile.avatarUrl')}</Label>
            <Input id="avatarUrl" inputMode="url" {...register('avatarUrl')} />
            {errors.avatarUrl && (
              <span className="field__error">
                {translateValidation(t, errors.avatarUrl.message)}
              </span>
            )}
          </div>
          <div className="profile-form__actions">
            <Button type="submit" disabled={!isDirty || isSubmitting}>
              {isSubmitting && <Loader2 className="h-4 w-4 animate-spin" />}
              {t('common.saveChanges')}
            </Button>
          </div>
        </form>
      )}
    </div>
  );
}
