import { Head, router, useForm } from '@inertiajs/react';
import {
    AlertTriangle,
    Mail,
    MailCheck,
    RotateCcw,
    Send,
    Server,
    Zap,
} from 'lucide-react';
import { FormField, NativeSelect } from '@/components/crm/native-select';
import { Callout, SectionCard } from '@/components/crm/page-header';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { cn } from '@/lib/utils';
import {
    destroy as destroyMail,
    test as testMail,
    update as updateMail,
} from '@/routes/mail';
import type { MailProvider, MailSettingsProps } from '@/types';

/**
 * Settings -> Email delivery.
 *
 * The server this installation sends from. Three ways to set it up, because
 * they are the three things a solar company actually has: a Gmail address, a
 * Brevo account for transactional mail, or the SMTP details their host gave
 * them. Customers never see any of it; they just get their verification link
 * and their password reset.
 */
export default function EmailSettings({ mail, presets }: MailSettingsProps) {
    const form = useForm({
        mailer: mail.mailer,
        host: mail.host ?? presets.gmail.host,
        port: String(mail.port),
        encryption: mail.encryption,
        username: mail.username ?? '',
        // Never prefilled: the stored password is not sent to the browser. A
        // blank field on save means "keep the one you already have".
        password: '',
        from_address: mail.from_address ?? '',
        from_name: mail.from_name,
    });

    const test = useForm({
        email: mail.from_address ?? mail.username ?? '',
    });

    const isGmail = form.data.mailer === 'gmail';
    const isBrevo = form.data.mailer === 'brevo';

    /**
     * Each preset carries the server details it implies. Gmail's and Brevo's
     * are fixed by the backend, so the fields are not shown for them; the
     * manual form starts from blank and the usual submission port rather than
     * carrying the previous host over.
     */
    const chooseMode = (mode: MailProvider) => {
        if (form.data.mailer === mode) {
            return;
        }

        form.setData('mailer', mode);
        form.setData('host', presets[mode].host);
        form.setData('port', String(presets[mode].port));
        form.setData('encryption', presets[mode].encryption);
    };

    const modes: MailProvider[] = ['gmail', 'brevo', 'manual'];

    /**
     * A Gmail address is also the sender a Gmail account is allowed to use, so
     * it is offered as the from address as soon as it is typed — unless one has
     * already been chosen.
     */
    const useUsernameAsSender = () => {
        if (form.data.from_address.trim() === '' && isGmail) {
            form.setData('from_address', form.data.username.trim());
        }
    };

    const presetIcon = (mode: MailProvider) => {
        if (mode === 'gmail') {
            return Mail;
        }

        return mode === 'brevo' ? Zap : Server;
    };

    const submit = () => {
        form.put(updateMail().url, {
            preserveScroll: true,
            onSuccess: () => form.setData('password', ''),
        });
    };

    const sendTest = () => {
        test.post(testMail().url, { preserveScroll: true });
    };

    const resetSettings = () => {
        if (
            !window.confirm(
                'Forget the saved email settings, including the password? Mail goes back to the way the server is configured.',
            )
        ) {
            return;
        }

        router.delete(destroyMail().url, { preserveScroll: true });
    };

    return (
        <>
            <Head title="Email delivery" />

            <Callout
                tone={mail.configured ? 'success' : 'warning'}
                icon={mail.configured ? MailCheck : AlertTriangle}
                title={
                    mail.configured
                        ? 'Mail is set up'
                        : 'Mail is not set up on this screen yet'
                }
            >
                {mail.configured ? (
                    mail.current
                ) : (
                    <>
                        Verification emails, password resets and job updates are
                        handled by the server configuration (
                        <span className="font-mono">{mail.transport}</span>).
                        Set an account below so customers actually receive them.
                    </>
                )}
            </Callout>

            <SectionCard
                title="How mail is sent"
                description="All three do the same job. Gmail is quickest; Brevo is built for transactional mail like verification links and password resets; the other server is whatever your host gave you."
                icon={Mail}
                tone="solar"
            >
                <div className="grid gap-3 sm:grid-cols-3">
                    {modes.map((mode) => {
                        const preset = presets[mode];
                        const active = form.data.mailer === mode;
                        const ModeIcon = presetIcon(mode);

                        return (
                            <button
                                key={mode}
                                type="button"
                                onClick={() => chooseMode(mode)}
                                aria-pressed={active}
                                className={cn(
                                    'flex flex-col items-start gap-1 rounded-xl p-4 text-left transition-colors',
                                    active
                                        ? 'bg-solar-soft ring-1 ring-solar/30'
                                        : 'bg-transparent ring-1 ring-hairline hover:bg-accent/50',
                                )}
                            >
                                <span className="flex items-center gap-2 text-sm font-medium">
                                    <ModeIcon className="size-4 text-solar-ink" />
                                    {preset.label}
                                </span>
                                <span className="text-xs leading-relaxed text-muted-foreground">
                                    {preset.description}
                                </span>
                            </button>
                        );
                    })}
                </div>
            </SectionCard>

            <SectionCard
                title={
                    isGmail
                        ? 'Gmail account'
                        : isBrevo
                          ? 'Brevo account'
                          : 'SMTP server'
                }
                description={
                    isGmail
                        ? 'The Google account mail is sent from. Gmail sends through smtp.gmail.com on port 587, so there is nothing else to fill in.'
                        : isBrevo
                          ? `Brevo sends through ${presets.brevo.host} on port ${presets.brevo.port}, so there is nothing to look up. Both values are on the SMTP page of the Brevo dashboard.`
                          : 'The details your email provider gave you. The host is usually something like smtp.yourhost.com.'
                }
                icon={isGmail ? Mail : isBrevo ? Zap : Server}
                tone="info"
            >
                <div className="grid gap-x-6 gap-y-4 md:grid-cols-2">
                    {isGmail ? (
                        <FormField
                            label="Gmail address"
                            htmlFor="username"
                            error={form.errors.username}
                            hint="The account the mail is sent from"
                            required
                            className="md:col-span-2"
                        >
                            <Input
                                id="username"
                                type="email"
                                autoComplete="email"
                                value={form.data.username}
                                placeholder="orders@yourcompany.com.au"
                                onChange={(event) => {
                                    form.setData(
                                        'username',
                                        event.target.value,
                                    );
                                    useUsernameAsSender();
                                }}
                                onBlur={useUsernameAsSender}
                            />
                        </FormField>
                    ) : isBrevo ? (
                        <>
                            <FormField
                                label="Brevo SMTP login"
                                htmlFor="username"
                                error={form.errors.username}
                                hint="The Login shown under Settings → SMTP & API → SMTP"
                                required
                                className="md:col-span-2"
                            >
                                <Input
                                    id="username"
                                    autoComplete="username"
                                    value={form.data.username}
                                    placeholder="orders@yourcompany.com.au"
                                    onChange={(event) =>
                                        form.setData(
                                            'username',
                                            event.target.value,
                                        )
                                    }
                                />
                            </FormField>

                            <div className="md:col-span-2">
                                <p className="text-xs text-muted-foreground">
                                    Server{' '}
                                    <span className="font-mono text-foreground">
                                        {presets.brevo.host}
                                    </span>
                                    , port{' '}
                                    <span className="font-mono text-foreground">
                                        {presets.brevo.port}
                                    </span>{' '}
                                    with STARTTLS. If your network blocks 587,
                                    Brevo also listens on 2525.
                                </p>
                            </div>
                        </>
                    ) : (
                        <>
                            <FormField
                                label="SMTP host"
                                htmlFor="host"
                                error={form.errors.host}
                                hint="From your email provider"
                                required
                            >
                                <Input
                                    id="host"
                                    value={form.data.host}
                                    placeholder="smtp.yourhost.com"
                                    onChange={(event) =>
                                        form.setData('host', event.target.value)
                                    }
                                />
                            </FormField>

                            <FormField
                                label="Port"
                                htmlFor="port"
                                error={form.errors.port}
                                hint="587 for STARTTLS, 465 for SSL"
                                required
                            >
                                <Input
                                    id="port"
                                    type="number"
                                    inputMode="numeric"
                                    min={1}
                                    max={65535}
                                    value={form.data.port}
                                    placeholder="587"
                                    onChange={(event) =>
                                        form.setData('port', event.target.value)
                                    }
                                />
                            </FormField>

                            <FormField
                                label="Encryption"
                                htmlFor="encryption"
                                error={form.errors.encryption}
                                hint="Most servers use STARTTLS"
                                required
                            >
                                <NativeSelect
                                    id="encryption"
                                    value={form.data.encryption}
                                    onChange={(event) =>
                                        form.setData(
                                            'encryption',
                                            event.target
                                                .value as typeof form.data.encryption,
                                        )
                                    }
                                >
                                    <option value="tls">
                                        STARTTLS (port 587)
                                    </option>
                                    <option value="ssl">
                                        SSL / implicit TLS (port 465)
                                    </option>
                                    <option value="none">No encryption</option>
                                </NativeSelect>
                            </FormField>

                            <FormField
                                label="Username"
                                htmlFor="username"
                                error={form.errors.username}
                                hint="Often the full email address"
                            >
                                <Input
                                    id="username"
                                    autoComplete="username"
                                    value={form.data.username}
                                    placeholder="orders@yourcompany.com.au"
                                    onChange={(event) =>
                                        form.setData(
                                            'username',
                                            event.target.value,
                                        )
                                    }
                                />
                            </FormField>
                        </>
                    )}

                    <FormField
                        label={
                            isGmail
                                ? 'App password'
                                : isBrevo
                                  ? 'SMTP key'
                                  : 'Password'
                        }
                        htmlFor="password"
                        error={form.errors.password}
                        hint={
                            mail.has_password
                                ? 'A password is saved. Leave this blank to keep it.'
                                : isGmail
                                  ? 'The 16-character app password from your Google Account'
                                  : isBrevo
                                    ? 'From Brevo: Settings → SMTP & API → SMTP keys. Not your account password.'
                                    : 'The password for the username above'
                        }
                        className="md:col-span-2"
                    >
                        <Input
                            id="password"
                            type="password"
                            autoComplete="new-password"
                            value={form.data.password}
                            placeholder={
                                mail.has_password
                                    ? '••••••••••••••••'
                                    : isGmail
                                      ? 'abcd efgh ijkl mnop'
                                      : isBrevo
                                        ? 'xsmtpsib-…'
                                        : ''
                            }
                            onChange={(event) =>
                                form.setData('password', event.target.value)
                            }
                        />
                    </FormField>
                </div>

                {isGmail ? (
                    <div className="mt-4">
                        <Callout
                            tone="info"
                            title="Gmail needs an app password"
                        >
                            Google does not let an application sign in with your
                            normal password. Turn on 2-Step Verification, then
                            create an app password at{' '}
                            <a
                                href="https://myaccount.google.com/apppasswords"
                                target="_blank"
                                rel="noreferrer"
                                className="font-medium underline underline-offset-2"
                            >
                                myaccount.google.com/apppasswords
                            </a>{' '}
                            and paste it above. Spaces in it are fine.
                        </Callout>
                    </div>
                ) : null}

                {isBrevo ? (
                    <div className="mt-4">
                        <Callout tone="info" title="Brevo needs an SMTP key">
                            Generate one at{' '}
                            <a
                                href="https://app.brevo.com/settings/keys/smtp"
                                target="_blank"
                                rel="noreferrer"
                                className="font-medium underline underline-offset-2"
                            >
                                app.brevo.com/settings/keys/smtp
                            </a>{' '}
                            and paste it above. It is a separate credential from
                            the API keys, and Brevo shows it only once.
                        </Callout>
                    </div>
                ) : null}
            </SectionCard>

            <SectionCard
                title="Who mail comes from"
                description={
                    isBrevo
                        ? 'What a customer sees in their inbox. Brevo only sends from a verified sender, or from any address on a domain you have authenticated with them.'
                        : 'What a customer sees in their inbox. A business address here reads better than a personal one, and is less likely to be filed as spam.'
                }
                icon={MailCheck}
                tone="slate"
            >
                <div className="grid gap-x-6 gap-y-4 md:grid-cols-2">
                    <FormField
                        label="Sender address"
                        htmlFor="from_address"
                        error={form.errors.from_address}
                        hint={
                            isBrevo
                                ? 'Verified at Brevo under Senders, or on your authenticated domain'
                                : 'The address replies go to'
                        }
                        required
                    >
                        <Input
                            id="from_address"
                            type="email"
                            value={form.data.from_address}
                            placeholder="orders@yourcompany.com.au"
                            onChange={(event) =>
                                form.setData('from_address', event.target.value)
                            }
                        />
                    </FormField>

                    <FormField
                        label="Sender name"
                        htmlFor="from_name"
                        error={form.errors.from_name}
                        hint="The company name in the inbox"
                    >
                        <Input
                            id="from_name"
                            value={form.data.from_name}
                            placeholder={mail.defaults.from_name}
                            onChange={(event) =>
                                form.setData('from_name', event.target.value)
                            }
                        />
                    </FormField>
                </div>
            </SectionCard>

            <SectionCard
                title="Send a test email"
                description="Proves the account works before a customer needs a password reset. Save first if you have just changed something."
                icon={Send}
                tone="emerald"
            >
                <div className="flex flex-col gap-3 sm:flex-row sm:items-start">
                    <FormField
                        label="Send to"
                        htmlFor="test_email"
                        error={test.errors.email}
                        hint="Your own address is the usual choice"
                        className="flex-1"
                    >
                        <Input
                            id="test_email"
                            type="email"
                            value={test.data.email}
                            placeholder="you@yourcompany.com.au"
                            onChange={(event) =>
                                test.setData('email', event.target.value)
                            }
                        />
                    </FormField>

                    <div className="sm:pt-6">
                        <Button
                            type="button"
                            variant="outline"
                            onClick={sendTest}
                            disabled={test.processing || !mail.configured}
                        >
                            <Send />
                            {test.processing ? 'Sending…' : 'Send test email'}
                        </Button>
                    </div>
                </div>

                {!mail.configured ? (
                    <p className="mt-3 text-xs text-muted-foreground">
                        Save an email account above before sending a test.
                    </p>
                ) : null}
            </SectionCard>

            <div className="flex flex-col-reverse gap-3 border-t border-hairline pt-4 sm:flex-row sm:items-center sm:justify-between">
                <p className="text-xs text-muted-foreground">
                    {form.recentlySuccessful
                        ? 'Saved.'
                        : 'Used for every email this installation sends.'}
                </p>
                <div className="flex flex-wrap items-center gap-2">
                    <Button
                        type="button"
                        variant="outline"
                        onClick={resetSettings}
                        disabled={form.processing || !mail.configured}
                    >
                        <RotateCcw />
                        Clear settings
                    </Button>
                    <Button
                        type="button"
                        onClick={submit}
                        disabled={form.processing}
                    >
                        {form.processing ? 'Saving…' : 'Save email settings'}
                    </Button>
                </div>
            </div>
        </>
    );
}
