'use client';

import { useRef, useState } from 'react';
import { Camera, Loader2 } from 'lucide-react';
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Button } from '@/components/ui/button';
import { useToast } from '@/components/id/toast-provider';
import { useAvatarUrl } from '@/hooks/use-avatar-url';
import { apiFetch, getApiErrorMessage } from '@/lib/api';

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

export function AvatarUpload({
  userId,
  displayName,
  hasAvatar,
  token,
  onUpdated
}: {
  userId: string;
  displayName?: string;
  hasAvatar?: boolean;
  token: string | null;
  onUpdated: () => Promise<void>;
}) {
  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
      );

      const uploadResponse = await fetch(presigned.uploadUrl, {
        method: 'PUT',
        headers: { 'Content-Type': file.type },
        body: file
      });

      if (!uploadResponse.ok) {
        throw new Error('Не удалось загрузить файл в хранилище');
      }

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

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

  return (
    <div className="relative inline-flex">
      <Avatar className="h-24 w-24 border-4 border-white shadow-xl">
        {avatarUrl ? <AvatarImage src={avatarUrl} alt={displayName ?? 'Аватар'} /> : null}
        <AvatarFallback className="bg-[linear-gradient(135deg,#6f58ff,#ffd2a8)] text-2xl">{initials}</AvatarFallback>
      </Avatar>
      <input ref={inputRef} type="file" accept="image/jpeg,image/png,image/webp,image/gif" className="hidden" onChange={handleFileChange} />
      <Button
        type="button"
        size="sm"
        variant="secondary"
        className="absolute -bottom-2 left-1/2 -translate-x-1/2 rounded-full px-3 shadow"
        disabled={isUploading || !token}
        onClick={() => inputRef.current?.click()}
      >
        {isUploading ? <Loader2 className="h-4 w-4 animate-spin" /> : <Camera className="h-4 w-4" />}
        {isUploading ? 'Загрузка...' : 'Фото'}
      </Button>
    </div>
  );
}

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

  return (
    <Avatar className={className}>
      {avatarUrl ? <AvatarImage src={avatarUrl} alt={displayName ?? 'Аватар'} /> : null}
      <AvatarFallback className="bg-[linear-gradient(135deg,#6f58ff,#ffd2a8)]">{initials}</AvatarFallback>
    </Avatar>
  );
}
