"use client";

import { useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { api, type AuthProvider, type AuthPreset } from "@/lib/api";
import { Button, Card } from "@/components/ui";
import { Field, inputClass } from "./Field";
import { SectionCard } from "./SectionCard";
import { ProviderIcon } from "./ProviderIcon";

function IdentityIcon() {
    return (
        <svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
            <path
                strokeLinecap="round"
                strokeLinejoin="round"
                d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.964 0a9 9 0 10-11.964 0m11.964 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z"
            />
        </svg>
    );
}

function CallbackRow({ url }: { url: string }) {
    const [copied, setCopied] = useState(false);
    return (
        <div className="flex items-center gap-2">
            <code className="flex-1 overflow-x-auto rounded bg-well px-2 py-1.5 font-mono text-xs text-text-primary">{url}</code>
            <Button
                type="button"
                variant="ghost"
                size="sm"
                onClick={async () => {
                    await navigator.clipboard.writeText(url);
                    setCopied(true);
                    setTimeout(() => setCopied(false), 2000);
                }}
            >
                {copied ? "Copied!" : "Copy"}
            </Button>
        </div>
    );
}

function AddProviderForm({ presets, onDone }: { presets: AuthPreset[]; onDone: () => void }) {
    const [preset, setPreset] = useState<string>("google");
    const [name, setName] = useState("");
    const [issuerInput, setIssuerInput] = useState("");
    const [clientId, setClientId] = useState("");
    const [clientSecret, setClientSecret] = useState("");

    const chosen = presets.find((p) => p.id === preset);

    const { mutate: create, isPending, error } = useMutation({
        mutationFn: () =>
            api.createAuthProvider({
                name: name || chosen?.label || "Single sign-on",
                preset,
                issuer_input: issuerInput,
                client_id: clientId,
                client_secret: clientSecret,
                enabled: true,
            }),
        onSuccess: onDone,
    });

    return (
        <form
            onSubmit={(e) => {
                e.preventDefault();
                create();
            }}
            className="space-y-4 rounded border border-border bg-surface-2 p-4"
        >
            <Field label="Provider type">
                <select value={preset} onChange={(e) => setPreset(e.target.value)} className={inputClass}>
                    {presets.map((p) => (
                        <option key={p.id || "custom"} value={p.id}>
                            {p.label}
                        </option>
                    ))}
                </select>
            </Field>

            <Field label="Button label" hint="What members see on the sign-in page.">
                <input type="text" required value={name} onChange={(e) => setName(e.target.value)} placeholder={chosen?.label ?? ""} className={inputClass} />
            </Field>

            {chosen?.input_label && (
                <Field label={chosen.input_label} hint={chosen.input_hint}>
                    <input type="text" required value={issuerInput} onChange={(e) => setIssuerInput(e.target.value)} className={inputClass} />
                </Field>
            )}

            <Field label="Client ID">
                <input type="text" required value={clientId} onChange={(e) => setClientId(e.target.value)} className={inputClass} />
            </Field>

            <Field label="Client secret">
                <input type="password" required autoComplete="new-password" value={clientSecret} onChange={(e) => setClientSecret(e.target.value)} className={inputClass} />
            </Field>

            {error && <div className="rounded border border-danger/30 bg-danger/10 px-3 py-2 text-sm text-danger">{(error as Error).message}</div>}

            <div className="flex items-center gap-3">
                <Button type="submit" variant="primary" loading={isPending}>
                    Add provider
                </Button>
                <Button type="button" variant="ghost" onClick={onDone}>
                    Cancel
                </Button>
            </div>
            <p className="text-xs text-text-tertiary">You will get a callback URL to register with your provider once it is added.</p>
        </form>
    );
}

function ProviderRow({ p }: { p: AuthProvider }) {
    const queryClient = useQueryClient();
    const [secret, setSecret] = useState("");
    const [testResult, setTestResult] = useState<{ ok: boolean; message: string } | null>(null);
    const invalidate = () => queryClient.invalidateQueries({ queryKey: ["auth-providers"] });

    const { mutate: update, error: updateError } = useMutation({
        mutationFn: (patch: Parameters<typeof api.updateAuthProvider>[1]) => api.updateAuthProvider(p.provider_id, patch),
        onSuccess: () => {
            setSecret("");
            invalidate();
        },
    });
    const { mutate: remove, error: deleteError } = useMutation({
        mutationFn: () => api.deleteAuthProvider(p.provider_id),
        onSuccess: invalidate,
    });
    const { mutate: test, isPending: testing } = useMutation({
        mutationFn: () => api.testAuthProvider(p.provider_id),
        onSuccess: setTestResult,
    });
    const { mutate: ack } = useMutation({
        mutationFn: () => api.ackAuthProviderNotice(p.provider_id),
        onSuccess: invalidate,
    });

    const error = (updateError ?? deleteError) as Error | null;

    return (
        <div className="space-y-3 rounded border border-border bg-surface-2 p-4">
            <div className="flex items-center gap-3">
                <ProviderIcon preset={p.preset} className="h-5 w-5 text-text-secondary" />
                <div className="flex-1">
                    <p className="text-sm font-medium text-text-primary">{p.name}</p>
                    <p className="text-xs text-text-tertiary">{p.issuer || "GitHub"}</p>
                </div>
                <label className="flex items-center gap-2 text-sm text-text-secondary">
                    <input
                        type="checkbox"
                        checked={p.enabled}
                        onChange={(e) => update({ enabled: e.target.checked })}
                        className="h-4 w-4 rounded-sm border-border bg-surface-2 accent-accent"
                    />
                    Enabled
                </label>
            </div>

            {p.callback_notice && (
                <div className="space-y-2 rounded border border-warning/30 bg-warning/10 px-3 py-2 text-sm text-warning">
                    <p>This provider&apos;s callback URL has changed. Update it in your identity provider or sign-in will fail.</p>
                    <Button type="button" variant="ghost" size="sm" onClick={() => ack()}>
                        I&apos;ve updated it
                    </Button>
                </div>
            )}

            <div>
                <p className="mb-1.5 text-xs font-medium text-text-secondary">Callback URL to register with this provider:</p>
                <CallbackRow url={p.callback_url} />
            </div>

            <div className="flex items-end gap-2">
                <div className="flex-1">
                    <Field label="Replace client secret" hint={p.client_secret_set ? "A secret is stored. Leave blank to keep it." : "No secret stored."}>
                        <input type="password" autoComplete="new-password" value={secret} onChange={(e) => setSecret(e.target.value)} className={inputClass} />
                    </Field>
                </div>
                <Button type="button" variant="secondary" disabled={!secret} onClick={() => update({ client_secret: secret })}>
                    Save
                </Button>
            </div>

            {testResult && (
                <div className={`rounded border px-3 py-2 text-sm ${testResult.ok ? "border-success/30 bg-success/10 text-success" : "border-danger/30 bg-danger/10 text-danger"}`}>
                    {testResult.message}
                </div>
            )}

            {error && <div className="rounded border border-danger/30 bg-danger/10 px-3 py-2 text-sm text-danger">{error.message}</div>}

            <div className="flex items-center gap-2">
                <Button type="button" variant="ghost" size="sm" loading={testing} onClick={() => test()}>
                    Test connection
                </Button>
                <Button type="button" variant="ghost" size="sm" onClick={() => remove()}>
                    Remove
                </Button>
            </div>
        </div>
    );
}

export function AuthProvidersCard({ localLoginEnabled, onLocalLoginChange }: { localLoginEnabled: boolean; onLocalLoginChange: (v: boolean) => void }) {
    const queryClient = useQueryClient();
    const [adding, setAdding] = useState(false);
    const { data: providers, isLoading } = useQuery({ queryKey: ["auth-providers"], queryFn: api.listAuthProviders });
    const { data: presets } = useQuery({ queryKey: ["auth-presets"], queryFn: api.listAuthPresets });

    if (isLoading) {
        return (
            <Card>
                <div className="flex justify-center py-8">
                    <div className="h-6 w-6 animate-spin rounded-full border-2 border-border border-t-accent" />
                </div>
            </Card>
        );
    }

    const list = providers ?? [];
    const enabledCount = list.filter((p) => p.enabled).length;

    return (
        <SectionCard
            title="Sign-in providers"
            description="Members can sign in with any provider you add here. Users are provisioned into this instance on first sign-in."
            icon={<IdentityIcon />}
        >
            <div className="space-y-3">
                {list.length === 0 && <p className="text-sm text-text-tertiary">No providers configured. Members sign in with a password.</p>}
                {list.map((p) => (
                    <ProviderRow key={p.provider_id} p={p} />
                ))}
            </div>

            <div className="mt-4">
                {adding ? (
                    <AddProviderForm
                        presets={presets ?? []}
                        onDone={() => {
                            setAdding(false);
                            queryClient.invalidateQueries({ queryKey: ["auth-providers"] });
                        }}
                    />
                ) : (
                    <Button type="button" variant="secondary" onClick={() => setAdding(true)}>
                        Add provider
                    </Button>
                )}
            </div>

            <div className="mt-6 border-t border-border pt-4">
                <label className="flex items-center gap-2 text-sm text-text-secondary">
                    <input
                        type="checkbox"
                        checked={localLoginEnabled}
                        disabled={enabledCount === 0}
                        onChange={(e) => onLocalLoginChange(e.target.checked)}
                        className="h-4 w-4 rounded-sm border-border bg-surface-2 accent-accent"
                    />
                    Allow email and password sign-in
                </label>
                <p className="mt-1.5 text-xs text-text-tertiary">
                    {enabledCount === 0
                        ? "Enable at least one provider before turning this off, or nobody could sign in."
                        : "Turn this off to require members to use a provider above."}
                </p>
            </div>
        </SectionCard>
    );
}
