"use client"

import { useState, useRef } from "react"
import { useRouter } from "next/navigation"
import { Loader2, CheckCircle2, Camera, Trash2, UserCircle2 } from "lucide-react"
import { createClient } from "@/lib/supabase/client"
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 {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"
import { COUNTRIES, GENDERS } from "@/lib/countries"

type Initial = {
  display_name: string
  age: number
  gender: string
  country: string
  state: string
  bio: string | null
  avatar_url: string | null
}

// Max upload size. Profile photos should be modest — 5 MB is plenty for a
// high-quality square crop and keeps the public bucket tidy.
const MAX_AVATAR_BYTES = 5 * 1024 * 1024
const ACCEPTED_IMAGE_TYPES = ["image/jpeg", "image/png", "image/webp", "image/gif"]

export function ProfileForm({
  userId,
  email,
  initial,
}: {
  userId: string
  email: string
  initial: Initial
}) {
  const router = useRouter()
  const [name, setName] = useState(initial.display_name)
  const [age, setAge] = useState(String(initial.age))
  const [gender, setGender] = useState(initial.gender)
  const [country, setCountry] = useState(initial.country)
  const [state, setState] = useState(initial.state)
  const [bio, setBio] = useState(initial.bio ?? "")
  const [avatarUrl, setAvatarUrl] = useState<string | null>(initial.avatar_url)
  const [avatarBusy, setAvatarBusy] = useState(false)
  const [avatarError, setAvatarError] = useState<string | null>(null)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [saved, setSaved] = useState(false)
  const fileInputRef = useRef<HTMLInputElement>(null)

  // --- Avatar upload/delete ------------------------------------------------
  // Uploaded files live under `avatars/<userId>/avatar.<ext>` in a public
  // Supabase Storage bucket. The path is scoped to the user-id so RLS only
  // lets the owner write there. A cache-busting `?v=` query param is added
  // to the displayed URL so the old CDN-cached image is replaced the moment
  // the upload finishes.
  const onPickFile = () => {
    setAvatarError(null)
    fileInputRef.current?.click()
  }

  const onFileSelected = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0]
    // Reset the input so selecting the same file twice still fires `change`.
    if (e.target) e.target.value = ""
    if (!file) return

    if (!ACCEPTED_IMAGE_TYPES.includes(file.type)) {
      setAvatarError("Please pick a JPG, PNG, WEBP, or GIF image")
      return
    }
    if (file.size > MAX_AVATAR_BYTES) {
      setAvatarError("Image is too large — max 5 MB")
      return
    }

    setAvatarBusy(true)
    setAvatarError(null)
    try {
      const supabase = createClient()
      // Pick a deterministic filename per extension so uploads overwrite
      // the previous photo cleanly instead of accumulating old files.
      const ext = file.name.split(".").pop()?.toLowerCase() || "jpg"
      const safeExt = ["jpg", "jpeg", "png", "webp", "gif"].includes(ext) ? ext : "jpg"
      const path = `${userId}/avatar.${safeExt}`

      // Best-effort: delete any previously uploaded avatars with different
      // extensions so the bucket doesn't leak orphaned files. Errors are
      // ignored because the user may not have an existing photo.
      const { data: existing } = await supabase.storage
        .from("avatars")
        .list(userId, { limit: 10 })
      if (existing && existing.length > 0) {
        const toRemove = existing
          .map((f) => `${userId}/${f.name}`)
          .filter((p) => p !== path)
        if (toRemove.length > 0) {
          await supabase.storage.from("avatars").remove(toRemove)
        }
      }

      const { error: uploadError } = await supabase.storage
        .from("avatars")
        .upload(path, file, {
          upsert: true,
          contentType: file.type,
          cacheControl: "3600",
        })
      if (uploadError) throw uploadError

      const { data: publicData } = supabase.storage
        .from("avatars")
        .getPublicUrl(path)
      const publicUrl = `${publicData.publicUrl}?v=${Date.now()}`

      const { error: updateError } = await supabase
        .from("profiles")
        .update({ avatar_url: publicUrl })
        .eq("id", userId)
      if (updateError) throw updateError

      setAvatarUrl(publicUrl)
      router.refresh()
    } catch (err) {
      setAvatarError(
        err instanceof Error ? err.message : "Could not upload photo",
      )
    } finally {
      setAvatarBusy(false)
    }
  }

  const onDeleteAvatar = async () => {
    setAvatarBusy(true)
    setAvatarError(null)
    try {
      const supabase = createClient()
      // Remove all files under the user's folder so no orphan remains.
      const { data: existing } = await supabase.storage
        .from("avatars")
        .list(userId, { limit: 20 })
      if (existing && existing.length > 0) {
        await supabase.storage
          .from("avatars")
          .remove(existing.map((f) => `${userId}/${f.name}`))
      }

      const { error: updateError } = await supabase
        .from("profiles")
        .update({ avatar_url: null })
        .eq("id", userId)
      if (updateError) throw updateError

      setAvatarUrl(null)
      router.refresh()
    } catch (err) {
      setAvatarError(
        err instanceof Error ? err.message : "Could not remove photo",
      )
    } finally {
      setAvatarBusy(false)
    }
  }

  // --- Profile form save ---------------------------------------------------
  const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault()
    setError(null)
    setSaved(false)

    if (!name.trim()) return setError("Name is required")
    const ageNum = Number.parseInt(age, 10)
    if (!Number.isFinite(ageNum) || ageNum < 13 || ageNum > 120) {
      return setError("Please enter a valid age between 13 and 120")
    }
    if (!gender) return setError("Please select your gender")
    if (!country) return setError("Please select your country")
    if (!state.trim()) return setError("Please enter your state or region")

    setLoading(true)
    try {
      const supabase = createClient()
      const { error: updateError } = await supabase
        .from("profiles")
        .update({
          display_name: name.trim(),
          age: ageNum,
          gender,
          country,
          state: state.trim(),
          bio: bio.trim() ? bio.trim() : null,
        })
        .eq("id", userId)

      if (updateError) throw updateError

      await supabase.auth.updateUser({
        data: {
          display_name: name.trim(),
          age: String(ageNum),
          gender,
          country,
          state: state.trim(),
        },
      })

      setSaved(true)
      router.refresh()
    } catch (err) {
      setError(err instanceof Error ? err.message : "Could not save profile")
    } finally {
      setLoading(false)
    }
  }

  return (
    <form onSubmit={onSubmit} className="flex flex-col gap-5">
      {/* Avatar block — sits above the form fields because the photo is
          the single most prominent profile element. */}
      <div className="flex flex-col items-center gap-3 border-b border-border pb-5 sm:flex-row sm:items-center sm:gap-5">
        <div className="relative">
          <div className="flex h-24 w-24 items-center justify-center overflow-hidden rounded-full border border-border bg-muted text-muted-foreground shadow-sm">
            {avatarUrl ? (
              // Using a plain <img> on purpose: the URL points at the
              // Supabase Storage CDN and carries a cache-busting `?v=`
              // query param, which is simpler than configuring next/image
              // remote patterns for every Supabase project URL.
              // eslint-disable-next-line @next/next/no-img-element
              <img
                src={avatarUrl || "/placeholder.svg"}
                alt="Profile photo"
                className="h-full w-full object-cover"
              />
            ) : (
              <UserCircle2 className="h-12 w-12" aria-hidden="true" />
            )}
          </div>
          {avatarBusy && (
            <div className="absolute inset-0 flex items-center justify-center rounded-full bg-background/70">
              <Loader2 className="h-5 w-5 animate-spin text-foreground" aria-hidden="true" />
            </div>
          )}
        </div>

        <div className="flex flex-1 flex-col items-center gap-2 sm:items-start">
          <p className="text-sm font-medium text-foreground">Profile photo</p>
          <p className="text-center text-xs text-muted-foreground sm:text-left">
            JPG, PNG, WEBP, or GIF. Up to 5 MB.
          </p>
          <div className="flex flex-wrap justify-center gap-2 sm:justify-start">
            <input
              ref={fileInputRef}
              type="file"
              accept={ACCEPTED_IMAGE_TYPES.join(",")}
              className="sr-only"
              onChange={onFileSelected}
            />
            <Button
              type="button"
              variant="secondary"
              size="sm"
              onClick={onPickFile}
              disabled={avatarBusy}
              className="h-9 gap-1.5"
            >
              <Camera className="h-4 w-4" aria-hidden="true" />
              {avatarUrl ? "Change photo" : "Upload photo"}
            </Button>
            {avatarUrl && (
              <Button
                type="button"
                variant="ghost"
                size="sm"
                onClick={onDeleteAvatar}
                disabled={avatarBusy}
                className="h-9 gap-1.5 text-destructive hover:text-destructive"
              >
                <Trash2 className="h-4 w-4" aria-hidden="true" />
                Remove
              </Button>
            )}
          </div>
          {avatarError && (
            <p className="text-xs text-destructive">{avatarError}</p>
          )}
        </div>
      </div>

      <div>
        <p className="text-sm font-medium text-foreground">Account</p>
        <p className="text-xs text-muted-foreground">
          Email <span className="font-mono text-foreground">{email}</span> — cannot be changed
        </p>
      </div>

      <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
        <div className="flex flex-col gap-1.5">
          <Label htmlFor="name">
            Name <span className="text-destructive">*</span>
          </Label>
          <Input
            id="name"
            required
            value={name}
            onChange={(e) => setName(e.target.value)}
          />
        </div>
        <div className="flex flex-col gap-1.5">
          <Label htmlFor="age">
            Age <span className="text-destructive">*</span>
          </Label>
          <Input
            id="age"
            type="number"
            inputMode="numeric"
            min={13}
            max={120}
            required
            value={age}
            onChange={(e) => setAge(e.target.value)}
          />
        </div>
      </div>

      <div className="flex flex-col gap-1.5">
        <Label htmlFor="gender">
          Gender <span className="text-destructive">*</span>
        </Label>
        <Select value={gender} onValueChange={setGender}>
          <SelectTrigger id="gender">
            <SelectValue placeholder="Select gender" />
          </SelectTrigger>
          <SelectContent>
            {GENDERS.map((g) => (
              <SelectItem key={g.value} value={g.value}>
                {g.label}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      </div>

      <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
        <div className="flex flex-col gap-1.5">
          <Label htmlFor="country">
            Country <span className="text-destructive">*</span>
          </Label>
          <Select value={country} onValueChange={setCountry}>
            <SelectTrigger id="country">
              <SelectValue placeholder="Select country" />
            </SelectTrigger>
            <SelectContent className="max-h-72">
              {COUNTRIES.map((c) => (
                <SelectItem key={c} value={c}>
                  {c}
                </SelectItem>
              ))}
              {/* Preserve any legacy value that isn't in COUNTRIES */}
              {!COUNTRIES.includes(country as (typeof COUNTRIES)[number]) && country && (
                <SelectItem value={country}>{country}</SelectItem>
              )}
            </SelectContent>
          </Select>
        </div>
        <div className="flex flex-col gap-1.5">
          <Label htmlFor="state">
            State / Region <span className="text-destructive">*</span>
          </Label>
          <Input
            id="state"
            required
            value={state}
            onChange={(e) => setState(e.target.value)}
          />
        </div>
      </div>

      <div className="flex flex-col gap-1.5">
        <Label htmlFor="bio">About you</Label>
        <Textarea
          id="bio"
          rows={3}
          placeholder="A short bio (optional)"
          value={bio}
          onChange={(e) => setBio(e.target.value)}
          maxLength={280}
        />
        <p className="text-right text-[11px] text-muted-foreground">{bio.length}/280</p>
      </div>

      {error && (
        <p className="rounded-md bg-destructive/10 px-3 py-2 text-xs text-destructive">{error}</p>
      )}
      {saved && !error && (
        <p className="flex items-center gap-1.5 rounded-md bg-emerald-50 px-3 py-2 text-xs text-emerald-700 dark:bg-emerald-950 dark:text-emerald-300">
          <CheckCircle2 className="h-3.5 w-3.5" aria-hidden="true" />
          Saved
        </p>
      )}

      <div className="flex items-center justify-end gap-2">
        <Button type="submit" disabled={loading} className="min-w-32">
          {loading ? (
            <>
              <Loader2 className="mr-2 h-4 w-4 animate-spin" aria-hidden="true" />
              Saving…
            </>
          ) : (
            "Save changes"
          )}
        </Button>
      </div>
    </form>
  )
}
