"use client";

import { useState, useRef } from "react";
import { useTranslations } from "next-intl";
import { toast } from "sonner";
import { Camera, Loader2, X } from "lucide-react";
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import { uploadToPresignedPost } from "@/lib/upload-client";

export function AvatarUploader({
  name,
  image,
  hasCustomAvatar,
  onChange,
}: {
  name: string;
  image: string | null;
  hasCustomAvatar: boolean;
  onChange: (image: string | null, hasCustomAvatar: boolean) => void;
}) {
  const t = useTranslations("settingsForm");
  const [uploading, setUploading] = useState(false);
  const [preview, setPreview] = useState<string | null>(null);
  const inputRef = useRef<HTMLInputElement>(null);

  async function handleFile(file: File) {
    setUploading(true);
    setPreview(URL.createObjectURL(file));
    try {
      const presignRes = await fetch("/api/v1/upload/avatar-presign", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ contentType: file.type, fileSize: file.size }),
      });
      if (!presignRes.ok) {
        const err = await presignRes.json() as { error?: string };
        toast.error(err.error ?? t("avatarUploadFailed"));
        return;
      }
      const { url, fields, key } = await presignRes.json() as { url: string; fields: Record<string, string>; key: string };
      const uploaded = await uploadToPresignedPost(url, fields, file);
      if (!uploaded) {
        toast.error(t("avatarUploadFailed"));
        return;
      }

      // Send back the storage key we were issued, not a client-derived URL —
      // the server validates the key belongs to us and builds the public URL
      // itself, so a client can't set avatarUrl to an arbitrary/unowned target.
      const saveRes = await fetch("/api/v1/users/me", {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ avatarKey: key }),
      });
      if (!saveRes.ok) {
        toast.error(t("avatarUploadFailed"));
        return;
      }
      const saved = await saveRes.json() as { avatarUrl?: string };
      onChange(saved.avatarUrl ?? null, true);
      toast.success(t("avatarUploadSuccess"));
    } finally {
      setUploading(false);
    }
  }

  async function handleRemove() {
    setUploading(true);
    try {
      const res = await fetch("/api/v1/users/me", {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ avatarUrl: null }),
      });
      if (!res.ok) {
        toast.error(t("avatarUploadFailed"));
        return;
      }
      const saved = await res.json() as { avatarUrl?: string };
      setPreview(null);
      onChange(saved.avatarUrl ?? null, false);
      toast.success(t("avatarRemoved"));
    } finally {
      setUploading(false);
    }
  }

  return (
    <div className="flex items-center gap-4">
      <div className="relative">
        <Avatar size="lg" className="size-16">
          <AvatarImage src={preview ?? image ?? undefined} alt={name} />
          <AvatarFallback className="text-lg">{name.slice(0, 2).toUpperCase()}</AvatarFallback>
        </Avatar>
        {uploading && (
          <div className="absolute inset-0 flex items-center justify-center rounded-full bg-black/40">
            <Loader2 className="h-5 w-5 animate-spin text-white" />
          </div>
        )}
      </div>
      <div className="flex flex-col gap-1.5">
        <input
          ref={inputRef}
          type="file"
          accept="image/jpeg,image/png,image/webp,image/avif"
          className="hidden"
          onChange={(e) => {
            const file = e.target.files?.[0];
            if (file) void handleFile(file);
            e.target.value = "";
          }}
        />
        <Button type="button" variant="outline" size="sm" onClick={() => inputRef.current?.click()} disabled={uploading}>
          <Camera className="h-4 w-4" />
          {t("changePhoto")}
        </Button>
        {hasCustomAvatar && (
          <button
            type="button"
            onClick={() => { void handleRemove(); }}
            disabled={uploading}
            className="flex items-center gap-1 text-xs text-muted-foreground hover:text-destructive transition-colors disabled:opacity-50"
          >
            <X className="h-3 w-3" />
            {t("removePhoto")}
          </button>
        )}
      </div>
    </div>
  );
}
