"use client"

import * as React from "react"
import { useTranslations } from "next-intl"
import { Loader2, Trash2, Upload } from "lucide-react"
import { toast } from "sonner"

import { removeUserAvatarAction, updateUserAvatarAction } from "@/modules/settings/actions-avatar"
import type { FileUploadResult } from "@/modules/files/types"
import { Avatar, AvatarFallback, AvatarImage } from "@/shared/components/ui/avatar"
import { Button } from "@/shared/components/ui/button"

interface AvatarUploadProps {
  /** 当前头像 URL */
  currentImage: string | null
  /** 用户显示名（用于 fallback） */
  name: string | null
  /** 用户邮箱（用于 fallback） */
  email: string
  /** 头像更新后的回调 */
  onUpdated?: (imageUrl: string | null) => void
}

const ACCEPTED_IMAGE_TYPES = ["image/jpeg", "image/png", "image/webp", "image/gif"] as const
const MAX_AVATAR_SIZE = 2 * 1024 * 1024 // 2MB
const MAX_FILENAME_LENGTH = 255

/**
 * 头像上传组件
 *
 * 支持上传新头像、预览、删除。
 * 文件通过 /api/upload 上传（targetType="user_avatar" 已注册到 FileTargetType 枚举），
 * 成功后调用 Server Action 更新 users.image。
 */
export function AvatarUpload({
  currentImage,
  name,
  email,
  onUpdated,
}: AvatarUploadProps): React.ReactElement {
  const t = useTranslations("settings.profile.avatar")
  const [uploading, setUploading] = React.useState(false)
  const [removing, setRemoving] = React.useState(false)
  const [previewUrl, setPreviewUrl] = React.useState<string | null>(currentImage)
  const inputRef = React.useRef<HTMLInputElement>(null)

  React.useEffect(() => {
    setPreviewUrl(currentImage)
  }, [currentImage])

  const validateFile = (file: File): string | null => {
    if (file.name.length > MAX_FILENAME_LENGTH) {
      return t("tooLongName")
    }
    if (!ACCEPTED_IMAGE_TYPES.includes(file.type as (typeof ACCEPTED_IMAGE_TYPES)[number])) {
      return t("invalidType")
    }
    if (file.size > MAX_AVATAR_SIZE) {
      return t("tooLarge")
    }
    return null
  }

  const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>): Promise<void> => {
    const file = e.target.files?.[0]
    if (!file) return

    const error = validateFile(file)
    if (error) {
      toast.error(error)
      return
    }

    setUploading(true)
    try {
      // 上传文件到 /api/upload，targetType="user_avatar" 已注册到 FileTargetType 枚举
      const formData = new FormData()
      formData.append("file", file)
      formData.append("targetType", "user_avatar")

      const response = await fetch("/api/upload", {
        method: "POST",
        body: formData,
      })

      if (!response.ok) {
        const body = (await response.json().catch(() => ({}))) as { message?: string }
        throw new Error(body.message || "Upload failed")
      }

      const result = (await response.json()) as FileUploadResult

      // 调用 Server Action 更新用户头像
      const updateResult = await updateUserAvatarAction(result.url)
      if (!updateResult.success) {
        throw new Error(updateResult.message || "Failed to update avatar")
      }

      setPreviewUrl(result.url)
      onUpdated?.(result.url)
      toast.success(t("uploadSuccess"))
    } catch (error) {
      const message = error instanceof Error ? error.message : t("uploadFailure")
      toast.error(message)
    } finally {
      setUploading(false)
      if (inputRef.current) {
        inputRef.current.value = ""
      }
    }
  }

  const handleRemove = async (): Promise<void> => {
    setRemoving(true)
    try {
      const result = await removeUserAvatarAction()
      if (!result.success) {
        throw new Error(result.message || "Failed to remove avatar")
      }
      setPreviewUrl(null)
      onUpdated?.(null)
      toast.success(t("removeSuccess"))
    } catch (error) {
      const message = error instanceof Error ? error.message : t("removeFailure")
      toast.error(message)
    } finally {
      setRemoving(false)
    }
  }

  const fallbackText = (name ?? email).slice(0, 2).toUpperCase()

  return (
    <div className="flex items-center gap-4">
      <div className="relative group">
        <Avatar className="h-20 w-20">
          {previewUrl ? <AvatarImage src={previewUrl} alt={name ?? email} /> : null}
          <AvatarFallback className="text-xl font-semibold">{fallbackText}</AvatarFallback>
        </Avatar>
        {uploading ? (
          <div className="absolute inset-0 flex items-center justify-center rounded-full bg-black/50">
            <Loader2 className="h-5 w-5 animate-spin text-white" />
          </div>
        ) : null}
      </div>

      <div className="space-y-2">
        <div className="flex gap-2">
          <Button
            type="button"
            variant="outline"
            size="sm"
            disabled={uploading || removing}
            onClick={() => inputRef.current?.click()}
            className="gap-2"
          >
            <Upload className="h-4 w-4" />
            {t("upload")}
          </Button>
          {previewUrl ? (
            <Button
              type="button"
              variant="ghost"
              size="sm"
              disabled={uploading || removing}
              onClick={handleRemove}
              className="gap-2 text-destructive hover:text-destructive"
            >
              {removing ? <Loader2 className="h-4 w-4 animate-spin" /> : <Trash2 className="h-4 w-4" />}
              {t("remove")}
            </Button>
          ) : null}
        </div>
        <p className="text-xs text-muted-foreground">{t("hint")}</p>
      </div>

      <input
        ref={inputRef}
        type="file"
        accept={ACCEPTED_IMAGE_TYPES.join(",")}
        onChange={handleFileChange}
        className="sr-only"
        aria-label={t("upload")}
      />
    </div>
  )
}
