"use client" import { useEffect, useState } from "react" import { ChevronDown, ChevronUp, Loader2, Mail } from "lucide-react" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card" import { ProtonBridgeWizard } from "@/components/gmail/settings/proton-bridge-wizard" import { useDiscoverMailAccount } from "@/lib/api/hooks/use-mail-account-discover" import { useTestMailAccount } from "@/lib/api/hooks/use-mail-account-test" import { useStartMailOAuth } from "@/lib/api/hooks/use-mail-oauth" import { useMailOAuthProviders } from "@/lib/api/hooks/use-mail-oauth-providers" import type { CreateMailAccountPayload, MailAccountDiscoverResult } from "@/lib/api/types" import { manualMailDiscoverResult } from "@/lib/mail-settings/manual-account-discover" type Step = "email" | "proton" | "credentials" function displayNameFromEmail(email: string): string { const local = email.split("@")[0] ?? email return local.replace(/[._-]+/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()) } function usernameForHint(email: string, hint: string): string { if (hint === "local") { return email.split("@")[0] ?? email } return email } function shouldShowAdvanced(discover: MailAccountDiscoverResult | null): boolean { if (!discover) return true if (discover.confidence === "low") return true if (!discover.imap_host || !discover.smtp_host) return true if (discover.provider_id === "tutanota") return true return false } function oauthProviderForDiscover( discover: MailAccountDiscoverResult, enabled: string[] ): "google" | "microsoft" | null { if (!discover.auth_methods.includes("oauth2")) return null const id = discover.provider_id if ((id === "gmail" || id === "google_workspace") && enabled.includes("google")) { return "google" } if ( (id === "outlook" || id === "microsoft365") && enabled.includes("microsoft") ) { return "microsoft" } return null } export function AddMailAccountForm({ pending, onSubmit, }: { pending: boolean onSubmit: (payload: CreateMailAccountPayload) => void }) { const [open, setOpen] = useState(false) const [step, setStep] = useState("email") const [showAdvanced, setShowAdvanced] = useState(false) const [discover, setDiscover] = useState(null) const [testOk, setTestOk] = useState(null) const discoverMutation = useDiscoverMailAccount() const testMutation = useTestMailAccount() const oauthStart = useStartMailOAuth() const { data: oauthProviders } = useMailOAuthProviders() const enabledOAuth = oauthProviders?.providers ?? [] const [email, setEmail] = useState("") const [form, setForm] = useState({ name: "", imap_host: "127.0.0.1", imap_port: "1143", imap_tls: true, smtp_host: "127.0.0.1", smtp_port: "1025", smtp_tls: true, username: "", password: "", }) useEffect(() => { if (!discover) return setForm((prev) => ({ ...prev, imap_host: discover.imap_host || prev.imap_host, imap_port: String(discover.imap_port || 993), imap_tls: discover.imap_tls, smtp_host: discover.smtp_host || prev.smtp_host, smtp_port: String(discover.smtp_port || 587), smtp_tls: discover.smtp_tls, username: prev.username || usernameForHint(discover.email, discover.username_hint), name: prev.name || displayNameFromEmail(discover.email), })) setShowAdvanced(shouldShowAdvanced(discover)) setTestOk(null) }, [discover]) function resetForm() { setStep("email") setEmail("") setDiscover(null) setShowAdvanced(false) setTestOk(null) setForm({ name: "", imap_host: "127.0.0.1", imap_port: "1143", imap_tls: true, smtp_host: "127.0.0.1", smtp_port: "1025", smtp_tls: true, username: "", password: "", }) discoverMutation.reset() testMutation.reset() oauthStart.reset() } async function handleEmailContinue() { const trimmed = email.trim() if (!trimmed) return const result = await discoverMutation.mutateAsync(trimmed) goToCredentials(result) } function goToCredentials(result: MailAccountDiscoverResult) { setDiscover(result) if (result.provider_id === "proton" && result.source !== "manual") { setStep("proton") } else { setStep("credentials") } } function handleManualContinue() { const trimmed = email.trim() if (!trimmed || !trimmed.includes("@")) return goToCredentials(manualMailDiscoverResult(trimmed)) } async function runConnectionTest() { const result = await testMutation.mutateAsync({ imap_host: form.imap_host, imap_port: Number(form.imap_port) || 993, imap_tls: form.imap_tls, smtp_host: form.smtp_host, smtp_port: Number(form.smtp_port) || 587, smtp_tls: form.smtp_tls, username: form.username, password: form.password, }) setTestOk(result.ok) return result } async function handleProtonContinue() { setForm((prev) => ({ ...prev, imap_host: "127.0.0.1", smtp_host: "127.0.0.1", username: discover?.email ?? prev.username, password: prev.password, })) const result = await runConnectionTest() if (result.ok) { setStep("credentials") } } function handleSubmit() { if (!discover) return onSubmit({ name: form.name.trim() || displayNameFromEmail(discover.email), email: discover.email, provider: discover.provider_id, imap_host: form.imap_host, imap_port: Number(form.imap_port) || 993, imap_tls: form.imap_tls, smtp_host: form.smtp_host, smtp_port: Number(form.smtp_port) || 587, smtp_tls: form.smtp_tls, username: form.username, password: form.password, }) setOpen(false) resetForm() } async function handleOAuth(provider: "google" | "microsoft") { if (!discover) return const { authorization_url } = await oauthStart.mutateAsync({ provider, email: discover.email, name: form.name.trim() || displayNameFromEmail(discover.email), provider_id: discover.provider_id, imap_host: form.imap_host, imap_port: Number(form.imap_port) || 993, imap_tls: form.imap_tls, smtp_host: form.smtp_host, smtp_port: Number(form.smtp_port) || 587, smtp_tls: form.smtp_tls, }) window.location.href = authorization_url } const oauthProvider = discover ? oauthProviderForDiscover(discover, enabledOAuth) : null if (!open) { return ( ) } return ( Nouveau compte mail Saisissez votre adresse e-mail : nous détectons le fournisseur et préremplissons IMAP/SMTP. {step === "email" ? (
{discoverMutation.isError ? (

Détection impossible. Utilisez « Configurer manuellement » ou réessayez.

) : null}

La détection préremplit IMAP/SMTP. Choisissez « Configurer manuellement » pour saisir vos paramètres sans appel réseau.

) : null} {step === "proton" && discover ? ( setForm({ ...form, password: v })} onImapPortChange={(v) => setForm({ ...form, imap_port: v })} onSmtpPortChange={(v) => setForm({ ...form, smtp_port: v })} onContinue={() => void handleProtonContinue()} onBack={() => setStep("email")} /> ) : null} {step === "credentials" && discover ? ( <> setStep("email")} /> {discover.notes?.length ? (
    {discover.notes.map((note) => (
  • {note}
  • ))}
) : null} {oauthProvider ? (

Connexion recommandée sans mot de passe :

ou identifiant / mot de passe ci-dessous

) : null}
setForm({ ...form, name: v })} /> setForm({ ...form, username: v })} autoComplete="username" /> { setTestOk(null) setForm({ ...form, password: v }) }} autoComplete="current-password" />
{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}

)}
) : null}
) } function TestResultBanner({ testing, result, testOk, error, }: { testing: boolean result?: { ok: boolean; imap_ok: boolean; imap_error?: string; smtp_ok: boolean; smtp_error?: string } testOk: boolean | null error: boolean }) { if (testing || testOk === null) { if (error) { return

Échec du test de connexion.

} return null } if (testOk && result?.ok) { return (

Connexion IMAP et SMTP validée.

) } return (

Échec du test de connexion.

{result?.imap_error ?

IMAP : {result.imap_error}

: null} {result?.smtp_error ?

SMTP : {result.smtp_error}

: null}
) } function ProviderBanner({ discover, onBack, }: { discover: MailAccountDiscoverResult onBack: () => void }) { return (

{discover.email}

{discover.provider_name} {discover.confidence !== "high" ? ` · confiance ${discover.confidence}` : 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)} />
) }