"use client"

import { useEffect, useMemo, useRef, useState } from "react"
import { Loader2 } from "lucide-react"
import { AuthConnectButton } from "@/components/auth/auth-connect-button"
import { PasswordFieldBlock } from "@/components/auth/password-field-block"
import {
  isSignupCredentialsStep,
  SignupCredentialsFields,
} from "@/components/auth/signup-credentials-fields"
import { buildSignupEmail } from "@/lib/auth/signup-platform"
import { AUTH_FLOW_SLUGS } from "@/lib/auth/auth-flow-slugs"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import type { FlowChallenge } from "@/lib/auth/flow-api"

type PromptField = {
  field_key: string
  label?: string
  type?: string
  required?: boolean
  placeholder?: string
  initial_value?: string
  choices?: Array<{ label?: string; value?: string }>
}

type FlowChallengeFormProps = {
  challenge: FlowChallenge | null
  component: string
  submitting: boolean
  fieldErrors?: Record<string, string>
  flowSlug?: string
  onSubmit: (payload: Record<string, unknown>) => void | Promise<void>
}

export function FlowChallengeForm({
  challenge,
  component,
  submitting,
  fieldErrors = {},
  flowSlug,
  onSubmit,
}: FlowChallengeFormProps) {
  const [values, setValues] = useState<Record<string, string>>({})
  const [signupCanSubmit, setSignupCanSubmit] = useState(true)
  const initializedComponentRef = useRef<string | null>(null)

  const promptFields = useMemo(() => readPromptFields(challenge), [challenge])
  const primaryAction = readPrimaryAction(challenge)
  const signupCredentials =
    flowSlug === AUTH_FLOW_SLUGS.enrollment &&
    component === "ak-stage-prompt" &&
    isSignupCredentialsStep(promptFields)

  useEffect(() => {
    if (!signupCredentials) {
      setSignupCanSubmit(true)
    }
  }, [signupCredentials])

  useEffect(() => {
    if (initializedComponentRef.current === component) return
    initializedComponentRef.current = component

    const next: Record<string, string> = {}
    if (component === "ak-stage-prompt") {
      for (const field of promptFields) {
        if (field.type === "hidden" || field.type === "static") continue
        next[field.field_key] = field.initial_value ?? ""
      }
    }
    if (component === "ak-stage-identification") {
      next.uid_field = ""
      if (readPasswordFields(challenge)) {
        next.password = ""
      }
    }
    if (component === "ak-stage-email") {
      next.email = ""
    }
    setValues(next)
  }, [challenge, component, promptFields])

  async function handleSubmit(event: React.FormEvent) {
    event.preventDefault()
    const payload: Record<string, unknown> = { component }

    if (component === "ak-stage-prompt") {
      for (const field of promptFields) {
        const key = field.field_key
        if (field.type === "static") continue
        if (field.type === "hidden") {
          if (key === "email" && signupCredentials) {
            payload[key] = buildSignupEmail(values.username ?? "")
          } else {
            payload[key] = field.initial_value ?? ""
          }
          continue
        }
        payload[key] = values[key] ?? ""
      }
    } else if (component === "ak-stage-identification") {
      payload.uid_field = values.uid_field ?? ""
      if (readPasswordFields(challenge)) {
        payload.password = values.password ?? ""
      }
    } else if (component === "ak-stage-email") {
      payload.email = values.email ?? ""
    } else if (component === "ak-stage-authenticator-validate") {
      payload.code = values.code ?? ""
    } else {
      Object.assign(payload, values)
    }

    await onSubmit(payload)
  }

  if (!component || component === "ak-stage-access-denied") {
    return null
  }

  return (
    <form className="space-y-4" autoComplete="on" onSubmit={handleSubmit}>
      {component === "ak-stage-prompt" ? (
        signupCredentials ? (
          <SignupCredentialsFields
            fields={promptFields}
            values={values}
            fieldErrors={fieldErrors}
            onCanSubmitChange={setSignupCanSubmit}
            onChange={(key, value) =>
              setValues((prev) => ({ ...prev, [key]: value }))
            }
          />
        ) : (
          <PromptFields
            fields={promptFields}
            values={values}
            fieldErrors={fieldErrors}
            onChange={(key, value) =>
              setValues((prev) => ({ ...prev, [key]: value }))
            }
          />
        )
      ) : null}

      {component === "ak-stage-identification" ? (
        <IdentificationFields
          challenge={challenge}
          values={values}
          fieldErrors={fieldErrors}
          onChange={(key, value) =>
            setValues((prev) => ({ ...prev, [key]: value }))
          }
        />
      ) : null}

      {component === "ak-stage-email" ? (
        <FieldBlock
          id="email"
          label="Adresse e-mail"
          type="email"
          autoComplete="email"
          value={values.email ?? ""}
          error={fieldErrors.email}
          onChange={(value) => setValues((prev) => ({ ...prev, email: value }))}
          required
        />
      ) : null}

      {component === "ak-stage-authenticator-validate" ? (
        <FieldBlock
          id="code"
          label="Code de validation"
          type="text"
          inputMode="numeric"
          autoComplete="one-time-code"
          value={values.code ?? ""}
          onChange={(value) => setValues((prev) => ({ ...prev, code: value }))}
          required
        />
      ) : null}

      {!isKnownComponent(component) ? (
        <p className="text-sm text-muted-foreground">
          Étape non prise en charge ({component}). Utilisez le portail Authentik.
        </p>
      ) : null}

      {isKnownComponent(component) ? (
        <AuthConnectButton
          type="submit"
          disabled={submitting || (signupCredentials && !signupCanSubmit)}
        >
          {submitting ? (
            <>
              <Loader2 className="size-4 animate-spin" aria-hidden />
              <span>Patientez…</span>
            </>
          ) : (
            primaryAction
          )}
        </AuthConnectButton>
      ) : null}
    </form>
  )
}

function PromptFields({
  fields,
  values,
  fieldErrors,
  onChange,
}: {
  fields: PromptField[]
  values: Record<string, string>
  fieldErrors: Record<string, string>
  onChange: (key: string, value: string) => void
}) {
  return (
    <div className="space-y-4">
      {fields.map((field) => {
        if (field.type === "hidden") return null
        if (field.type === "static") {
          return (
            <p key={field.field_key} className="text-sm text-muted-foreground">
              {field.label}
              {field.initial_value ? (
                <span className="font-medium text-foreground">
                  {" "}
                  {field.initial_value}
                </span>
              ) : null}
            </p>
          )
        }

        const inputType =
          field.type === "password"
            ? "password"
            : field.type === "email"
              ? "email"
              : "text"

        if (field.type === "file") {
          return (
            <div key={field.field_key} 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(field.field_key, "")
                    return
                  }
                  const reader = new FileReader()
                  reader.onload = () => {
                    onChange(field.field_key, String(reader.result ?? ""))
                  }
                  reader.readAsDataURL(file)
                }}
              />
            </div>
          )
        }

        if (field.type === "password") {
          return (
            <PasswordFieldBlock
              key={field.field_key}
              id={field.field_key}
              label={field.label ?? field.field_key}
              value={values[field.field_key] ?? ""}
              error={fieldErrors[field.field_key]}
              required={field.required}
              autoComplete={
                field.field_key.includes("repeat") ? "new-password" : "new-password"
              }
              showStrength={field.field_key === "password"}
              compareWith={
                field.field_key === "password_repeat"
                  ? (values.password ?? "")
                  : undefined
              }
              onChange={(value) => onChange(field.field_key, value)}
            />
          )
        }

        return (
          <FieldBlock
            key={field.field_key}
            id={field.field_key}
            label={field.label ?? field.field_key}
            type={inputType}
            placeholder={field.placeholder}
            value={values[field.field_key] ?? ""}
            error={fieldErrors[field.field_key]}
            onChange={(value) => onChange(field.field_key, value)}
            required={field.required}
            autoComplete={autoCompleteFor(field.field_key, field.type)}
          />
        )
      })}
    </div>
  )
}

function IdentificationFields({
  challenge,
  values,
  fieldErrors,
  onChange,
}: {
  challenge: FlowChallenge | null
  values: Record<string, string>
  fieldErrors: Record<string, string>
  onChange: (key: string, value: string) => void
}) {
  const withPassword = readPasswordFields(challenge)
  const userFields = readUserFields(challenge)
  const label =
    userFields.includes("email") && !userFields.includes("username")
      ? "Adresse e-mail"
      : "Identifiant"

  return (
    <div className="space-y-4">
      <FieldBlock
        id="uid_field"
        label={label}
        type={userFields.includes("email") ? "email" : "text"}
        autoComplete="username"
        value={values.uid_field ?? ""}
        error={fieldErrors.uid_field}
        onChange={(value) => onChange("uid_field", value)}
        required
      />
      {withPassword ? (
        <PasswordFieldBlock
          id="password"
          label="Mot de passe"
          value={values.password ?? ""}
          error={fieldErrors.password}
          required
          autoComplete="current-password"
          onChange={(value) => onChange("password", value)}
        />
      ) : null}
    </div>
  )
}

function FieldBlock({
  id,
  label,
  type = "text",
  placeholder,
  value,
  error,
  onChange,
  required,
  autoComplete,
  inputMode,
}: {
  id: string
  label: string
  type?: string
  placeholder?: string
  value: string
  error?: string
  onChange: (value: string) => void
  required?: boolean
  autoComplete?: string
  inputMode?: React.HTMLAttributes<HTMLInputElement>["inputMode"]
}) {
  return (
    <div className="space-y-2">
      <Label htmlFor={id}>{label}</Label>
      <Input
        id={id}
        type={type}
        placeholder={placeholder}
        value={value}
        required={required}
        autoComplete={autoComplete}
        inputMode={inputMode}
        aria-invalid={error ? true : undefined}
        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 readPromptFields(challenge: FlowChallenge | null): PromptField[] {
  const raw = challenge?.fields
  if (!Array.isArray(raw)) return []
  return raw.filter(isPromptField)
}

function isPromptField(value: unknown): value is PromptField {
  return (
    typeof value === "object" &&
    value !== null &&
    typeof (value as PromptField).field_key === "string"
  )
}

function readPrimaryAction(challenge: FlowChallenge | null): string {
  const action = challenge?.primary_action
  return typeof action === "string" && action.trim() ? action : "Continuer"
}

function readPasswordFields(challenge: FlowChallenge | null): boolean {
  return challenge?.password_fields === true
}

function readUserFields(challenge: FlowChallenge | null): string[] {
  const raw = challenge?.user_fields
  if (!Array.isArray(raw)) return ["username"]
  return raw.filter((v): v is string => typeof v === "string")
}

function autoCompleteFor(fieldKey: string, type?: string): string | undefined {
  if (type === "password") {
    return fieldKey.includes("repeat") ? "new-password" : "new-password"
  }
  if (fieldKey === "username") return "username"
  if (fieldKey === "email" || fieldKey.includes("email")) return "email"
  if (fieldKey === "name") return "name"
  if (fieldKey.includes("phone")) return "tel"
  return undefined
}

function isKnownComponent(component: string): boolean {
  return [
    "ak-stage-prompt",
    "ak-stage-identification",
    "ak-stage-email",
    "ak-stage-authenticator-validate",
  ].includes(component)
}
