import { useEffect, useState } from "react";
import AppLayout from "@/Layouts/AppLayout";
import { Head, useForm, usePage } from "@inertiajs/react";
import { toast } from "sonner";
import {
    CheckCircle2,
    ChevronRight,
    FileText,
    KeyRound,
    Send,
    Server,
    Settings,
} from "lucide-react";
import PageHeader from "@/Components/PageHeader";
import { Badge } from "@/Components/ui/badge";
import { Button } from "@/Components/ui/button";
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from "@/Components/ui/dialog";
import { Input } from "@/Components/ui/input";
import { Label } from "@/Components/ui/label";
import { Switch } from "@/Components/ui/switch";
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from "@/Components/ui/select";

/**
 * Configurações · Tokens: credenciais dos serviços que a APLICAÇÃO usa — o PDFShift,
 * que transforma o relatório aprovado em PDF, e o provedor de e-mail que entrega esse
 * PDF ao cliente.
 *
 * Não confundir com Integrações, que guarda credencial de CLIENTE (Google Ads, Meta,
 * GA4 de cada projeto). Aqui é o que vale pro sistema inteiro.
 *
 * Nenhum segredo chega inteiro nesta tela: o backend manda só se existe e os 4 últimos
 * caracteres. Por isso todo campo de senha/chave começa vazio, mesmo com valor salvo, e
 * salvar em branco não apaga nada.
 */
export default function Tokens({ pdf = {}, smtp = {}, resend = {}, from = {}, fallback = {} }) {
    const { flash } = usePage().props;
    const [open, setOpen] = useState(null);

    // Um efeito só, na página: o flash é da página inteira. Um por cartão faria o mesmo
    // aviso aparecer uma vez para cada cartão aberto.
    useEffect(() => {
        if (flash?.success) toast.success(flash.success);
        if (flash?.error) toast.error(flash.error);
    }, [flash?.success, flash?.error]);

    // Os dois podem estar ativos ao mesmo tempo agora: o Resend é sempre tentado
    // primeiro, o SMTP só entra se ele falhar. A ordem da lista abaixo (Resend antes do
    // SMTP) segue essa prioridade, e o subtítulo avisa o papel de cada um quando os
    // dois estão ligados.
    const bothActive = smtp.enabled && resend.enabled;

    const items = [
        {
            key: "pdfshift",
            icon: FileText,
            title: "PDFShift",
            subtitle: "Gera o PDF de cada relatório aprovado",
            state: pdf.has_key
                ? { label: "Configurado", tone: "ok" }
                : { label: "Sem chave", tone: "warn" },
        },
        {
            key: "resend",
            icon: Send,
            title: "Resend",
            subtitle: bothActive ? "Ativo · prioridade de envio" : "Envio de e-mail por API",
            state: resend.enabled
                ? { label: "Ativo", tone: "ok" }
                : { label: "Desativado", tone: "off" },
        },
        {
            key: "smtp",
            icon: Server,
            title: "SMTP",
            subtitle: bothActive
                ? "Ativo · reserva, entra se o Resend falhar"
                : smtp.host || "Servidor de e-mail próprio",
            state: smtp.enabled
                ? { label: "Ativo", tone: "ok" }
                : { label: "Desativado", tone: "off" },
        },
    ];

    return (
        <AppLayout>
            <Head title="Tokens" />

            <div className="mx-auto flex w-full max-w-[1200px] flex-col gap-4">
                <PageHeader
                    title="Tokens"
                    breadcrumb={[{ label: "Configurações", href: "configuracoes.index", icon: Settings }]}
                />
                <p className="-mt-2 text-sm text-muted-foreground">
                    Chaves e credenciais dos serviços que o sistema usa. As credenciais de cada cliente
                    (Google Ads, Meta, GA4) ficam em Configurações · Integrações. 🔌
                </p>

                {fallback.in_use && (
                    <p className="rounded-md border border-amber-500/40 bg-amber-500/5 px-4 py-3 text-xs text-muted-foreground">
                        Nenhum provedor de e-mail ativo aqui. O envio está saindo pela configuração do
                        servidor{fallback.address ? `, como ${fallback.address}` : ""}. Ative o SMTP ou o
                        Resend abaixo para passar a controlar o envio por esta tela.
                    </p>
                )}

                {bothActive && (
                    <p className="rounded-md border border-sky-500/40 bg-sky-500/5 px-4 py-3 text-xs text-muted-foreground">
                        Resend e SMTP estão ativos. O Resend é tentado primeiro em todo envio; se ele
                        falhar (chave inválida, domínio não verificado, API fora do ar), o SMTP entra
                        automaticamente no lugar dele, sem precisar reenviar nada.
                    </p>
                )}

                <div className="divide-y rounded-md border">
                    {items.map((item) => (
                        <button
                            key={item.key}
                            type="button"
                            onClick={() => setOpen(item.key)}
                            className="flex w-full items-center gap-4 px-4 py-3 text-left transition-colors hover:bg-muted/50"
                        >
                            <item.icon className="h-5 w-5 shrink-0 text-muted-foreground" />
                            <div className="min-w-0 flex-1">
                                <p className="text-sm font-medium">{item.title}</p>
                                <p className="truncate text-xs text-muted-foreground">{item.subtitle}</p>
                            </div>
                            <StateBadge state={item.state} />
                            <ChevronRight className="h-4 w-4 shrink-0 text-muted-foreground" />
                        </button>
                    ))}
                </div>
            </div>

            <PdfShiftDialog
                pdf={pdf}
                open={open === "pdfshift"}
                onOpenChange={(v) => !v && setOpen(null)}
            />
            <SmtpDialog
                smtp={smtp}
                from={from}
                open={open === "smtp"}
                onOpenChange={(v) => !v && setOpen(null)}
            />
            <ResendDialog
                resend={resend}
                from={from}
                open={open === "resend"}
                onOpenChange={(v) => !v && setOpen(null)}
            />
        </AppLayout>
    );
}

function StateBadge({ state }) {
    return (
        <Badge
            variant="outline"
            className="hidden shrink-0 gap-1 rounded-full px-1.5 font-normal text-muted-foreground sm:inline-flex"
        >
            {state.tone === "ok" ? (
                <CheckCircle2 className="h-3.5 w-3.5 fill-emerald-500 text-white dark:text-background" />
            ) : (
                <span
                    className={`h-2 w-2 rounded-full ${
                        state.tone === "warn" ? "bg-amber-500" : "bg-zinc-400"
                    }`}
                />
            )}
            {state.label}
        </Badge>
    );
}

/** O aviso de chave já salva, igual nos três cartões. */
function SavedHint({ has, masked, missingText }) {
    if (!has) {
        return <p className="text-xs text-amber-600 dark:text-amber-500">{missingText}</p>;
    }

    return (
        <p className="flex items-center gap-1.5 text-xs text-muted-foreground">
            <KeyRound className="h-3.5 w-3.5" />
            Salva: <span className="font-mono">{masked}</span> · deixe em branco para manter
        </p>
    );
}

function PdfShiftDialog({ pdf, open, onOpenChange }) {
    const form = useForm({ pdfshift_api_key: "", remove: false });

    function save(e) {
        e.preventDefault();
        form.transform((data) => ({ ...data, _method: "put", remove: false }));
        form.post(route("configuracoes.tokens.pdfshift"), {
            preserveScroll: true,
            onSuccess: () => {
                form.reset();
                onOpenChange(false);
            },
            onError: (errors) => toast.error(Object.values(errors ?? {})[0] || "Não foi possível salvar a chave."),
        });
    }

    function remove() {
        if (!confirm("Remover a chave do PDFShift? Sem ela, relatórios aprovados não geram PDF.")) return;

        form.transform(() => ({ _method: "put", remove: true }));
        form.post(route("configuracoes.tokens.pdfshift"), {
            preserveScroll: true,
            onSuccess: () => {
                form.reset();
                onOpenChange(false);
            },
        });
    }

    return (
        <Dialog open={open} onOpenChange={onOpenChange}>
            <DialogContent className="sm:max-w-lg">
                <form onSubmit={save}>
                    <DialogHeader>
                        <DialogTitle>PDFShift</DialogTitle>
                        <DialogDescription>
                            O PDF de cada relatório aprovado é gerado pelo PDFShift e anexado ao e-mail
                            de envio.
                        </DialogDescription>
                    </DialogHeader>

                    <div className="grid gap-2 py-4">
                        <Label htmlFor="pdfshift_api_key">Chave da API</Label>
                        <Input
                            id="pdfshift_api_key"
                            type="password"
                            autoComplete="off"
                            value={form.data.pdfshift_api_key}
                            onChange={(e) => form.setData("pdfshift_api_key", e.target.value)}
                            placeholder={pdf.has_key ? "Deixe em branco para manter a chave atual" : "Cole aqui a chave da API"}
                            className="font-mono"
                        />
                        <SavedHint
                            has={pdf.has_key}
                            masked={pdf.masked_key}
                            missingText="Nenhuma chave configurada. Sem ela, relatórios aprovados não geram PDF nem são enviados."
                        />
                        {form.errors.pdfshift_api_key && (
                            <p className="text-xs text-destructive">{form.errors.pdfshift_api_key}</p>
                        )}
                    </div>

                    <DialogFooter className="gap-2">
                        {pdf.has_key && (
                            <Button type="button" variant="outline" onClick={remove} disabled={form.processing}>
                                Remover chave
                            </Button>
                        )}
                        <Button type="submit" disabled={form.processing || form.data.pdfshift_api_key.trim() === ""}>
                            {form.processing ? "Salvando..." : "Salvar"}
                        </Button>
                    </DialogFooter>
                </form>
            </DialogContent>
        </Dialog>
    );
}

/**
 * Campos de remetente e o botão de teste, iguais nos dois provedores de e-mail: o
 * remetente é um só (vale pro provedor que estiver ativo) e o teste também.
 */
function MailCommonFields({ form, onTest, testing, canTest }) {
    return (
        <>
            <div className="grid gap-2 sm:grid-cols-2">
                <div className="grid gap-2">
                    <Label htmlFor="from_address">E-mail do remetente</Label>
                    <Input
                        id="from_address"
                        type="email"
                        value={form.data.from_address}
                        onChange={(e) => form.setData("from_address", e.target.value)}
                        placeholder="relatorios@exent.com.br"
                    />
                    {form.errors.from_address && (
                        <p className="text-xs text-destructive">{form.errors.from_address}</p>
                    )}
                </div>
                <div className="grid gap-2">
                    <Label htmlFor="from_name">Nome do remetente</Label>
                    <Input
                        id="from_name"
                        value={form.data.from_name}
                        onChange={(e) => form.setData("from_name", e.target.value)}
                        placeholder="Exent"
                    />
                </div>
            </div>

            <div className="rounded-md border p-3">
                <p className="text-xs text-muted-foreground">
                    O teste sai na hora, sem passar pela fila, e mostra aqui o erro exato do provedor
                    caso ele recuse. Salve antes de testar.
                </p>
                <Button
                    type="button"
                    variant="outline"
                    size="sm"
                    className="mt-2"
                    onClick={onTest}
                    disabled={testing || !canTest}
                >
                    <Send className="mr-1.5 h-3.5 w-3.5" />
                    {testing ? "Enviando..." : "Enviar e-mail de teste"}
                </Button>
            </div>
        </>
    );
}

/** O teste manda pro e-mail de quem está logado — quem configura é quem confere. */
function useMailTest() {
    const { auth } = usePage().props;
    const test = useForm({ email: auth?.user?.email ?? "" });

    return {
        email: test.data.email,
        testing: test.processing,
        send: () =>
            test.post(route("configuracoes.tokens.teste"), {
                preserveScroll: true,
                onError: (errors) => toast.error(Object.values(errors ?? {})[0] || "Não foi possível enviar o teste."),
            }),
    };
}

function SmtpDialog({ smtp, from, open, onOpenChange }) {
    const form = useForm({
        enabled: !!smtp.enabled,
        host: smtp.host ?? "",
        port: smtp.port ? String(smtp.port) : "587",
        scheme: smtp.scheme ?? "smtp",
        username: smtp.username ?? "",
        password: "",
        from_address: from.address ?? "",
        from_name: from.name ?? "",
    });
    const { email, testing, send } = useMailTest();

    function save(e) {
        e.preventDefault();
        form.transform((data) => ({ ...data, _method: "put", port: data.port ? Number(data.port) : null }));
        form.post(route("configuracoes.tokens.smtp"), {
            preserveScroll: true,
            onSuccess: () => form.setData("password", ""),
            onError: (errors) => toast.error(Object.values(errors ?? {})[0] || "Não foi possível salvar o SMTP."),
        });
    }

    return (
        <Dialog open={open} onOpenChange={onOpenChange}>
            <DialogContent className="sm:max-w-lg">
                <form onSubmit={save}>
                    <DialogHeader>
                        <DialogTitle>SMTP</DialogTitle>
                        <DialogDescription>
                            Envio pelo servidor de e-mail da empresa. Com o Resend também ativo, o
                            Resend tem prioridade e este vira a reserva automática se ele falhar.
                        </DialogDescription>
                    </DialogHeader>

                    <div className="grid gap-4 py-4">
                        <div className="flex items-center justify-between rounded-md border px-3 py-2">
                            <div>
                                <Label htmlFor="smtp-enabled" className="cursor-pointer">
                                    Usar SMTP para enviar
                                </Label>
                                <p className="text-xs text-muted-foreground">
                                    Desligado, este provedor não entra mais no envio, nem como reserva.
                                </p>
                            </div>
                            <Switch
                                id="smtp-enabled"
                                checked={form.data.enabled}
                                onCheckedChange={(v) => form.setData("enabled", v)}
                            />
                        </div>

                        {/* Campos só com o provedor ligado: desligado eles não têm efeito
                            nenhum, e mostrá-los sugere que têm. */}
                        {form.data.enabled && (
                            <>
                                <div className="grid gap-2">
                                    <Label htmlFor="smtp-host">Servidor</Label>
                                    <Input
                                        id="smtp-host"
                                        value={form.data.host}
                                        onChange={(e) => form.setData("host", e.target.value)}
                                        placeholder="smtp.gmail.com"
                                    />
                                    {form.errors.host && <p className="text-xs text-destructive">{form.errors.host}</p>}
                                </div>

                                <div className="grid gap-2 sm:grid-cols-2">
                                    <div className="grid gap-2">
                                        <Label htmlFor="smtp-scheme">Criptografia</Label>
                                        <Select
                                            value={form.data.scheme}
                                            onValueChange={(v) => {
                                                form.setData("scheme", v);
                                                // A porta anda junto da criptografia; trocar uma sem a
                                                // outra é o erro clássico de configuração de SMTP.
                                                form.setData("port", v === "smtps" ? "465" : "587");
                                            }}
                                        >
                                            <SelectTrigger id="smtp-scheme"><SelectValue /></SelectTrigger>
                                            <SelectContent>
                                                <SelectItem value="smtp">STARTTLS · porta 587</SelectItem>
                                                <SelectItem value="smtps">SSL/TLS · porta 465</SelectItem>
                                            </SelectContent>
                                        </Select>
                                    </div>
                                    <div className="grid gap-2">
                                        <Label htmlFor="smtp-port">Porta</Label>
                                        <Input
                                            id="smtp-port"
                                            inputMode="numeric"
                                            value={form.data.port}
                                            onChange={(e) => form.setData("port", e.target.value)}
                                            className="tabular-nums"
                                        />
                                        {form.errors.port && <p className="text-xs text-destructive">{form.errors.port}</p>}
                                    </div>
                                </div>

                                <div className="grid gap-2">
                                    <Label htmlFor="smtp-username">Usuário</Label>
                                    <Input
                                        id="smtp-username"
                                        autoComplete="off"
                                        value={form.data.username}
                                        onChange={(e) => form.setData("username", e.target.value)}
                                        placeholder="andreza.lima@exent.com.br"
                                    />
                                </div>

                                <div className="grid gap-2">
                                    <Label htmlFor="smtp-password">Senha</Label>
                                    <Input
                                        id="smtp-password"
                                        type="password"
                                        autoComplete="new-password"
                                        value={form.data.password}
                                        onChange={(e) => form.setData("password", e.target.value)}
                                        placeholder={smtp.has_password ? "Deixe em branco para manter a atual" : "Senha de app"}
                                        className="font-mono"
                                    />
                                    <SavedHint
                                        has={smtp.has_password}
                                        masked={smtp.masked_password}
                                        missingText="Nenhuma senha salva. No Gmail/Google Workspace, use uma senha de app."
                                    />
                                </div>

                                <MailCommonFields
                                    form={form}
                                    onTest={send}
                                    testing={testing}
                                    canTest={!!smtp.enabled && !!email}
                                />
                            </>
                        )}
                    </div>

                    <DialogFooter>
                        <Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
                            Fechar
                        </Button>
                        <Button type="submit" disabled={form.processing}>
                            {form.processing ? "Salvando..." : "Salvar"}
                        </Button>
                    </DialogFooter>
                </form>
            </DialogContent>
        </Dialog>
    );
}

function ResendDialog({ resend, from, open, onOpenChange }) {
    const form = useForm({
        enabled: !!resend.enabled,
        api_key: "",
        from_address: from.address ?? "",
        from_name: from.name ?? "",
    });
    const { email, testing, send } = useMailTest();

    function save(e) {
        e.preventDefault();
        form.transform((data) => ({ ...data, _method: "put" }));
        form.post(route("configuracoes.tokens.resend"), {
            preserveScroll: true,
            onSuccess: () => form.setData("api_key", ""),
            onError: (errors) => toast.error(Object.values(errors ?? {})[0] || "Não foi possível salvar o Resend."),
        });
    }

    return (
        <Dialog open={open} onOpenChange={onOpenChange}>
            <DialogContent className="sm:max-w-lg">
                <form onSubmit={save}>
                    <DialogHeader>
                        <DialogTitle>Resend</DialogTitle>
                        <DialogDescription>
                            Envio por API, sem servidor de e-mail próprio. Ativo, é sempre tentado
                            primeiro. Com o SMTP também ativo, ele entra como reserva automática se o
                            Resend falhar.
                        </DialogDescription>
                    </DialogHeader>

                    <div className="grid gap-4 py-4">
                        <div className="flex items-center justify-between rounded-md border px-3 py-2">
                            <div>
                                <Label htmlFor="resend-enabled" className="cursor-pointer">
                                    Usar Resend para enviar
                                </Label>
                                <p className="text-xs text-muted-foreground">
                                    Desligado, este provedor não entra mais no envio.
                                </p>
                            </div>
                            <Switch
                                id="resend-enabled"
                                checked={form.data.enabled}
                                onCheckedChange={(v) => form.setData("enabled", v)}
                            />
                        </div>

                        {form.data.enabled && (
                            <>
                                <div className="grid gap-2">
                                    <Label htmlFor="resend-key">Chave da API</Label>
                                    <Input
                                        id="resend-key"
                                        type="password"
                                        autoComplete="off"
                                        value={form.data.api_key}
                                        onChange={(e) => form.setData("api_key", e.target.value)}
                                        placeholder={resend.has_key ? "Deixe em branco para manter a atual" : "re_..."}
                                        className="font-mono"
                                    />
                                    <SavedHint
                                        has={resend.has_key}
                                        masked={resend.masked_key}
                                        missingText="Nenhuma chave configurada."
                                    />
                                    {form.errors.api_key && (
                                        <p className="text-xs text-destructive">{form.errors.api_key}</p>
                                    )}
                                </div>

                                <p className="text-xs text-muted-foreground">
                                    O domínio do remetente precisa estar verificado no painel do Resend,
                                    senão ele recusa o envio.
                                </p>

                                <MailCommonFields
                                    form={form}
                                    onTest={send}
                                    testing={testing}
                                    canTest={!!resend.enabled && !!email}
                                />
                            </>
                        )}
                    </div>

                    <DialogFooter>
                        <Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
                            Fechar
                        </Button>
                        <Button type="submit" disabled={form.processing}>
                            {form.processing ? "Salvando..." : "Salvar"}
                        </Button>
                    </DialogFooter>
                </form>
            </DialogContent>
        </Dialog>
    );
}
