"use client"

import { useEffect, useMemo, useState } from "react"
import { Loader2 } from "lucide-react"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { PasswordFieldBlock } from "@/components/auth/password-field-block"
import { checkMailAddressAvailability } from "@/lib/auth/check-mail-address"
import {
  buildSignupEmail,
  normalizeSignupLocalPart,
  SIGNUP_MAIL_DOMAIN,
} from "@/lib/auth/signup-platform"
import { useDebouncedValue } from "@/lib/hooks/use-debounced-value"
import { cn } from "@/lib/utils"

type PromptField = {
  field_key: string
  label?: string
  type?: string
  required?: boolean
  placeholder?: string
}

type SignupCredentialsFieldsProps = {
  fields: PromptField[]
  values: Record<string, string>
  fieldErrors: Record<string, string>
  onChange: (key: string, value: string) => void
  onCanSubmitChange?: (canSubmit: boolean) => void
}

export function isSignupCredentialsStep(fields: PromptField[]): boolean {
  const keys = new Set(fields.map((field) => field.field_key))
  return keys.has("username") && keys.has("password") && keys.has("password_repeat")
}

export function SignupCredentialsFields({
  fields,
  values,
  fieldErrors,
  onChange,
  onCanSubmitChange,
}: SignupCredentialsFieldsProps) {
  const username = values.username ?? ""
  const normalizedLocal = useMemo(() => normalizeSignupLocalPart(username), [username])
  const previewEmail = buildSignupEmail(username)
  const debouncedLocal = useDebouncedValue(normalizedLocal, 1000)

  const [availability, setAvailability] = useState<
    "idle" | "checking" | "available" | "taken" | "error"
  >("idle")

  useEffect(() => {
    if (debouncedLocal.length < 2) {
      setAvailability("idle")
      return
    }

    let cancelled = false
    setAvailability("checking")

    void checkMailAddressAvailability(debouncedLocal, SIGNUP_MAIL_DOMAIN)
      .then((result) => {
        if (cancelled) return
        setAvailability(result.available ? "available" : "taken")
      })
      .catch(() => {
        if (cancelled) return
        setAvailability("error")
      })

    return () => {
      cancelled = true
    }
  }, [debouncedLocal])

  const canSubmit =
    normalizedLocal.length >= 2 &&
    availability !== "taken" &&
    availability !== "checking"

  useEffect(() => {
    onCanSubmitChange?.(canSubmit)
  }, [canSubmit, onCanSubmitChange])

  const otherFields = fields.filter(
    (field) =>
      field.type !== "hidden" &&
      field.type !== "static" &&
      !["username", "password", "password_repeat", "domain_hint"].includes(
        field.field_key
      )
  )

  return (
    <div className="space-y-4">
      <div className="space-y-2">
        <Label htmlFor="username">Adresse e-mail</Label>
        <div className="relative flex items-center">
          <Input
            id="username"
            name="username"
            type="text"
            inputMode="email"
            autoComplete="username"
            spellCheck={false}
            autoCapitalize="none"
            autoCorrect="off"
            placeholder={
              fields.find((field) => field.field_key === "username")?.placeholder ??
              "prenom.nom"
            }
            value={username}
            required
            aria-invalid={
              fieldErrors.username || availability === "taken" ? true : undefined
            }
            onChange={(event) =>
              onChange("username", normalizeSignupLocalPart(event.target.value))
            }
            onKeyDown={(event) => {
              if (event.key === "@") event.preventDefault()
            }}
            onPaste={(event) => {
              const text = event.clipboardData.getData("text")
              if (!text.includes("@")) return
              event.preventDefault()
              onChange("username", normalizeSignupLocalPart(text))
            }}
            className="h-10 rounded-lg pr-[9.5rem]"
          />
          <span
            className="pointer-events-none absolute inset-y-0 right-3 flex items-center text-sm text-muted-foreground"
            aria-hidden
          >
            @{SIGNUP_MAIL_DOMAIN}
          </span>
        </div>

        <input
          type="email"
          name="email"
          autoComplete="email"
          value={previewEmail}
          readOnly
          tabIndex={-1}
          aria-hidden
          className="sr-only"
        />

        <p className="text-xs text-muted-foreground">
          Votre adresse sera{" "}
          <span className="font-medium text-foreground">
            {previewEmail || `identifiant@${SIGNUP_MAIL_DOMAIN}`}
          </span>
        </p>

        <AvailabilityHint
          local={normalizedLocal}
          debouncedLocal={debouncedLocal}
          status={availability}
        />

        {fieldErrors.username ? (
          <p className="text-xs text-destructive" role="alert">
            {fieldErrors.username}
          </p>
        ) : null}
      </div>

      <PasswordFieldBlock
        id="password"
        label="Mot de passe"
        value={values.password ?? ""}
        error={fieldErrors.password}
        required
        autoComplete="new-password"
        showStrength
        onChange={(value) => onChange("password", value)}
      />

      <PasswordFieldBlock
        id="password_repeat"
        label="Confirmer le mot de passe"
        value={values.password_repeat ?? ""}
        error={fieldErrors.password_repeat}
        required
        autoComplete="new-password"
        compareWith={values.password ?? ""}
        onChange={(value) => onChange("password_repeat", value)}
      />

      {otherFields.map((field) => (
        <GenericSignupField
          key={field.field_key}
          field={field}
          value={values[field.field_key] ?? ""}
          error={fieldErrors[field.field_key]}
          onChange={(value) => onChange(field.field_key, value)}
        />
      ))}
    </div>
  )
}

function AvailabilityHint({
  local,
  debouncedLocal,
  status,
}: {
  local: string
  debouncedLocal: string
  status: "idle" | "checking" | "available" | "taken" | "error"
}) {
  if (local.length === 0) return null
  if (local.length < 2) {
    return (
      <p className="text-xs text-muted-foreground">
        Au moins 2 caractères avant le @.
      </p>
    )
  }

  if (local !== debouncedLocal || status === "checking") {
    return (
      <p className="flex items-center gap-1.5 text-xs text-muted-foreground">
        <Loader2 className="size-3 animate-spin" aria-hidden />
        Vérification de la disponibilité…
      </p>
    )
  }

  if (status === "available") {
    return (
      <p className="text-xs text-emerald-600 dark:text-emerald-400" role="status">
        Cette adresse est disponible.
      </p>
    )
  }

  if (status === "taken") {
    return (
      <p className="text-xs text-destructive" role="alert">
        Cette adresse est déjà prise.
      </p>
    )
  }

  if (status === "error") {
    return (
      <p className="text-xs text-muted-foreground">
        Impossible de vérifier la disponibilité pour le moment.
      </p>
    )
  }

  return null
}

function GenericSignupField({
  field,
  value,
  error,
  onChange,
}: {
  field: PromptField
  value: string
  error?: string
  onChange: (value: string) => void
}) {
  if (field.type === "file") {
    return (
      <div className="space-y-2">
        <Label htmlFor={field.field_key}>{field.label}</Label>
        <Input
          id={field.field_key}
          type="file"
          accept="image/*"
          onChange={(event) => {
            const file = event.target.files?.[0]
            if (!file) {
              onChange("")
              return
            }
            const reader = new FileReader()
            reader.onload = () => onChange(String(reader.result ?? ""))
            reader.readAsDataURL(file)
          }}
        />
      </div>
    )
  }

  return (
    <div className="space-y-2">
      <Label htmlFor={field.field_key}>{field.label}</Label>
      <Input
        id={field.field_key}
        type="text"
        value={value}
        required={field.required}
        autoComplete={autoCompleteForField(field.field_key)}
        onChange={(event) => onChange(event.target.value)}
        className="h-10 rounded-lg"
      />
      {error ? (
        <p className="text-xs text-destructive" role="alert">
          {error}
        </p>
      ) : null}
    </div>
  )
}

function autoCompleteForField(fieldKey: string): string | undefined {
  if (fieldKey === "name") return "name"
  if (fieldKey.includes("phone")) return "tel"
  return undefined
}
