'use client';

import { useRef, useState } from 'react';
import { Camera, Loader2 } from 'lucide-react';
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { useToast } from '@/components/id/toast-provider';
import { useAvatarUrl } from '@/hooks/use-avatar-url';
import { apiFetch, getApiErrorMessage, uploadMediaObject } from '@/lib/api';
import { dispatchAvatarUpdated } from '@/lib/avatar-events';
import { VerificationBadge } from '@/components/id/verification-badge';
import { cn } from '@/lib/utils';

interface PresignedUploadResponse {
  uploadUrl: string;
  storageKey: string;
  expiresAt: string;
  uploadToken?: string;
}

export function AvatarUpload({
  userId,
  displayName,
  hasAvatar,
  token,
  onUpdated,
  isVerified,
  verificationIcon,
  className = 'h-24 w-24',
  badgeSize = 'md'
}: {
  userId: string;
  displayName?: string;
  hasAvatar?: boolean;
  token: string | null;
  onUpdated: () => Promise<void>;
  isVerified?: boolean;
  verificationIcon?: string | null;
  className?: string;
  badgeSize?: 'xs' | 'sm' | 'md' | 'lg';
}) {
  const inputRef = useRef<HTMLInputElement>(null);
  const { showToast } = useToast();
  const [isUploading, setIsUploading] = useState(false);
  const { avatarUrl, refreshAvatarUrl } = useAvatarUrl(userId, hasAvatar, token);
  const initials = (displayName ?? '').slice(0, 2).toUpperCase() || 'ID';

  async function handleFileChange(event: React.ChangeEvent<HTMLInputElement>) {
    const file = event.target.files?.[0];
    if (!file || !token) return;

    if (!['image/jpeg', 'image/png', 'image/webp', 'image/gif'].includes(file.type)) {
      showToast('Допустимы только JPEG, PNG, WEBP или GIF');
      return;
    }

    setIsUploading(true);
    try {
      const presigned = await apiFetch<PresignedUploadResponse>(
        '/media/avatars/upload-url',
        {
          method: 'POST',
          body: JSON.stringify({ contentType: file.type })
        },
        token
      );

      await uploadMediaObject(presigned, file, file.type);

      await apiFetch('/media/avatars/confirm', {
        method: 'POST',
        body: JSON.stringify({ storageKey: presigned.storageKey })
      }, token);

      await onUpdated();
      await refreshAvatarUrl();
      dispatchAvatarUpdated(userId);
      showToast('Аватар обновлён');
    } catch (error) {
      const message = getApiErrorMessage(error, 'Не удалось загрузить аватар');
      if (message) showToast(message);
    } finally {
      setIsUploading(false);
      if (inputRef.current) inputRef.current.value = '';
    }
  }

  function openFilePicker() {
    if (isUploading || !token) return;
    inputRef.current?.click();
  }

  return (
    <div className="relative inline-flex shrink-0">
      <button
        type="button"
        className={cn('group relative rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#3390ec] focus-visible:ring-offset-2', className)}
        disabled={isUploading || !token}
        aria-label="Изменить фото профиля"
        onClick={openFilePicker}
      >
        <Avatar className={cn('border-4 border-white shadow-xl', className)}>
          {avatarUrl ? <AvatarImage src={avatarUrl} alt={displayName ?? 'Аватар'} /> : null}
          <AvatarFallback className="bg-[linear-gradient(135deg,#6f58ff,#ffd2a8)] text-2xl">{initials}</AvatarFallback>
        </Avatar>
        <span
          className={cn(
            'absolute inset-0 flex items-center justify-center rounded-full transition',
            isUploading ? 'bg-black/45 opacity-100' : 'bg-black/0 opacity-0 group-hover:bg-black/40 group-hover:opacity-100 group-focus-visible:bg-black/40 group-focus-visible:opacity-100'
          )}
        >
          {isUploading ? (
            <Loader2 className="h-5 w-5 animate-spin text-white" />
          ) : (
            <Camera className="h-5 w-5 text-white" />
          )}
        </span>
      </button>
      {isVerified ? (
        <VerificationBadge
          verificationIcon={verificationIcon}
          size={badgeSize}
          className="pointer-events-none absolute top-0 right-0 z-20"
        />
      ) : null}
      <input ref={inputRef} type="file" accept="image/jpeg,image/png,image/webp,image/gif" className="hidden" onChange={handleFileChange} />
    </div>
  );
}

export function AvatarDisplay({
  userId,
  displayName,
  hasAvatar,
  token,
  className,
  isVerified,
  verificationIcon,
  badgeSize = 'sm'
}: {
  userId: string;
  displayName?: string;
  hasAvatar?: boolean;
  token: string | null;
  className?: string;
  isVerified?: boolean;
  verificationIcon?: string | null;
  badgeSize?: 'xs' | 'sm' | 'md' | 'lg';
}) {
  const { avatarUrl } = useAvatarUrl(userId, hasAvatar, token);
  const initials = (displayName ?? '').slice(0, 2).toUpperCase() || 'ID';

  return (
    <div className="relative inline-flex shrink-0">
      <Avatar className={className}>
        {avatarUrl ? <AvatarImage src={avatarUrl} alt={displayName ?? 'Аватар'} /> : null}
        <AvatarFallback className="bg-[linear-gradient(135deg,#6f58ff,#ffd2a8)]">{initials}</AvatarFallback>
      </Avatar>
      {isVerified ? (
        <VerificationBadge
          verificationIcon={verificationIcon}
          size={badgeSize}
          className="absolute -top-0.5 -right-0.5 z-20"
        />
      ) : null}
    </div>
  );
}
