"use client" import { useEffect, useState } from "react" import { ChevronDown, ChevronUp, Loader2 } from "lucide-react" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { useMailAccount } from "@/lib/api/hooks/use-mail-account" import { useUpdateMailAccount } from "@/lib/api/hooks/use-mail-account-mutations" import { useTestMailAccount } from "@/lib/api/hooks/use-mail-account-test" import type { ApiMailAccount, ApiMailAccountDetail, UpdateMailAccountPayload } from "@/lib/api/types" function parsePort(value: string, fallback: number): number { const n = Number.parseInt(value, 10) return Number.isFinite(n) && n > 0 ? n : fallback } function asString(value: string | undefined | null): string { return value ?? "" } function trimField(value: string | undefined | null): string { return asString(value).trim() } type EditAccountFormState = { name: string email: string username: string password: string imap_host: string imap_port: string imap_tls: boolean smtp_host: string smtp_port: string smtp_tls: boolean } function formStateFromAccount( account: ApiMailAccount, detail?: ApiMailAccountDetail | null ): EditAccountFormState { const src = detail ?? account return { name: asString(src.name ?? account.name), email: asString(src.email ?? account.email), username: asString(detail?.username ?? detail?.email ?? account.email), password: "", imap_host: asString(detail?.imap_host ?? account.imap_host), imap_port: String(detail?.imap_port ?? 993), imap_tls: detail?.imap_tls ?? true, smtp_host: asString(detail?.smtp_host ?? account.smtp_host), smtp_port: String(detail?.smtp_port ?? 587), smtp_tls: detail?.smtp_tls ?? true, } } export function EditMailAccountForm({ account, onCancel, }: { account: ApiMailAccount onCancel: () => void }) { const { data: detail, isPending, isError, refetch } = useMailAccount(account.id) const updateAccount = useUpdateMailAccount(account.id) const testMutation = useTestMailAccount(account.id) const [showAdvanced, setShowAdvanced] = useState(false) const [testOk, setTestOk] = useState(null) const [form, setForm] = useState(() => formStateFromAccount(account)) const isOAuth = detail?.auth_type === "oauth2" useEffect(() => { if (!detail) return setForm(formStateFromAccount(account, detail)) setTestOk(null) }, [account, detail]) if (isPending && !detail) { return null } if (isError) { return (

Impossible de charger ce compte.

) } function buildPayload(): UpdateMailAccountPayload { return { name: trimField(form.name) || trimField(form.email), email: trimField(form.email), provider: detail?.provider, imap_host: trimField(form.imap_host), imap_port: parsePort(form.imap_port, 993), imap_tls: form.imap_tls, smtp_host: trimField(form.smtp_host), smtp_port: parsePort(form.smtp_port, 587), smtp_tls: form.smtp_tls, username: trimField(form.username), password: form.password || undefined, } } async function runConnectionTest() { setTestOk(null) try { const result = await testMutation.mutateAsync({ imap_host: trimField(form.imap_host), imap_port: parsePort(form.imap_port, 993), imap_tls: form.imap_tls, smtp_host: trimField(form.smtp_host), smtp_port: parsePort(form.smtp_port, 587), smtp_tls: form.smtp_tls, username: trimField(form.username) || undefined, password: form.password || undefined, ...(isOAuth ? { auth_type: "oauth2" as const } : {}), }) setTestOk(result.ok) } catch { setTestOk(false) } } const canTestConnection = Boolean(trimField(form.imap_host)) && Boolean(trimField(form.smtp_host)) function handleSave() { const payload = buildPayload() if (!isOAuth && form.password && testOk === false) return updateAccount.mutate(payload, { onSuccess: onCancel }) } const passwordChanged = Boolean(form.password) const canSave = !updateAccount.isPending && Boolean(trimField(form.email)) && Boolean(trimField(form.imap_host)) && Boolean(trimField(form.smtp_host)) && (isOAuth || Boolean(trimField(form.username))) && (!passwordChanged || testOk !== false) return (

Modifier la connexion

{isOAuth ? (

Compte connecté via OAuth {detail?.oauth_provider ? ` (${detail.oauth_provider})` : ""}. Vous pouvez ajuster le nom et les serveurs ; le mot de passe n'est pas utilisé.

) : null}
setForm({ ...form, name: v })} /> setForm({ ...form, email: v })} /> setForm({ ...form, username: v })} autoComplete="username" /> {!isOAuth ? ( { setTestOk(null) setForm({ ...form, password: v }) }} autoComplete="new-password" /> ) : null}
{showAdvanced ? (
setForm({ ...form, imap_host: v })} /> setForm({ ...form, imap_port: v })} /> setForm({ ...form, smtp_host: v })} /> setForm({ ...form, smtp_port: v })} />
) : (

Réception {form.imap_host}:{form.imap_port} · Envoi {form.smtp_host}:{form.smtp_port}

)}
{testOk === true ? (

Connexion IMAP et SMTP validée.

) : null} {testOk === false ? (

Échec du test de connexion.

{testMutation.data?.imap_error ? (

IMAP : {testMutation.data.imap_error}

) : null} {testMutation.data?.smtp_error ? (

SMTP : {testMutation.data.smtp_error}

) : null}
) : null} {!isOAuth && !passwordChanged ? (

Le mot de passe enregistré est utilisé si le champ ci-dessus est vide.

) : null}
) } function Field({ label, value, onChange, type = "text", autoComplete, placeholder, }: { label: string value: string onChange: (value: string) => void type?: string autoComplete?: string placeholder?: string }) { return (
onChange(e.target.value)} />
) }