'use client';

/**
 * Admin UI to generate / list / revoke executive_display tokens — the
 * login-less, device-locked credential for the Executive dashboard. Mirrors
 * NOCTokensManager; talks to /api/executive/tokens.
 */
import { useState, useEffect } from 'react';
import {
    Plus, Key, Trash2, Copy, Check, AlertTriangle, Clock,
    Shield, Globe, LayoutDashboard, RefreshCw,
} from 'lucide-react';
import { Section } from '@/components/layout/Section';
import { useToast } from '@/components/ui/Toast';
import { useConfirm } from '@/components/ui/ConfirmDialogProvider';
import { Button, IconButton } from '@/components/ui';

interface ExecToken {
    id: number;
    tokenPrefix: string;
    displayName: string;
    countryId: number | null;
    deviceName: string | null;
    locked: boolean;
    expiresAt: string | null;
    expiresIn: number | null;
    isExpired: boolean;
    isRevoked: boolean;
    isActive: boolean;
    lastUsedAt: string | null;
    createdAt: string;
    createdBy: { id: number; name: string; email: string };
}

interface Country { id: number; name: string; code: string }

const EXPIRY_OPTIONS = [
    { value: 1, label: '1 day' },
    { value: 7, label: '7 days' },
    { value: 30, label: '30 days' },
    { value: 90, label: '90 days' },
    { value: 365, label: '1 year' },
    { value: 0, label: 'Lifetime (Never Expires)' },
];

export function ExecutiveTokensManager() {
    const toast = useToast();
    const { confirm } = useConfirm();
    const [tokens, setTokens] = useState<ExecToken[]>([]);
    const [countries, setCountries] = useState<Country[]>([]);
    const [loading, setLoading] = useState(true);
    const [showForm, setShowForm] = useState(false);
    const [generatedToken, setGeneratedToken] = useState<string | null>(null);
    const [copied, setCopied] = useState(false);
    const [saving, setSaving] = useState(false);

    const [displayName, setDisplayName] = useState('');
    const [countryId, setCountryId] = useState<string>('');
    const [expiryDays, setExpiryDays] = useState<number>(30);
    const [deviceName, setDeviceName] = useState('');

    useEffect(() => {
        fetchTokens();
        fetchCountries();
    }, []);

    const fetchTokens = async () => {
        setLoading(true);
        try {
            const res = await fetch('/api/executive/tokens');
            const data = await res.json();
            if (data.success) setTokens(data.tokens);
        } catch (e) {
            console.error('Failed to fetch executive tokens:', e);
        } finally {
            setLoading(false);
        }
    };

    const fetchCountries = async () => {
        try {
            const res = await fetch('/api/countries');
            const data = await res.json();
            if (data.success) setCountries(data.countries);
        } catch (e) {
            console.error('Failed to fetch countries:', e);
        }
    };

    const handleGenerate = async () => {
        if (!displayName.trim() || saving) return;
        setSaving(true);
        try {
            const res = await fetch('/api/executive/tokens', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    displayName: displayName.trim(),
                    countryId: countryId || null,
                    expiryDays,
                    deviceName: deviceName.trim() || null,
                }),
            });
            const data = await res.json();
            if (data.success) {
                setGeneratedToken(data.token.fullToken);
                fetchTokens();
                setDisplayName('');
                setCountryId('');
                setExpiryDays(30);
                setDeviceName('');
            } else {
                toast.error('Failed to generate token', data.error);
            }
        } catch (e) {
            console.error('Failed to generate token:', e);
            toast.error('Failed to generate token', e instanceof Error ? e.message : undefined);
        } finally {
            setSaving(false);
        }
    };

    const handleRevoke = async (tokenId: number, tokenName: string) => {
        const ok = await confirm({
            title: `Revoke "${tokenName}"?`,
            description: 'This cannot be undone and any display using this token is logged out immediately.',
            confirmText: 'Revoke',
            variant: 'danger',
        });
        if (!ok) return;
        try {
            const res = await fetch('/api/executive/tokens', {
                method: 'DELETE',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ tokenId }),
            });
            if (res.ok) fetchTokens();
        } catch (e) {
            console.error('Failed to revoke token:', e);
        }
    };

    const copyToken = async () => {
        if (generatedToken) {
            await navigator.clipboard.writeText(generatedToken);
            setCopied(true);
            setTimeout(() => setCopied(false), 3000);
        }
    };

    const formatDate = (dateStr: string) =>
        new Date(dateStr).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' });

    const getCountryName = (id: number | null) => (!id ? 'All Countries' : countries.find((c) => c.id === id)?.name || 'Unknown');

    if (loading) {
        return (
            <Section title="Executive Dashboard Tokens">
                <div className="p-8 text-center text-slate-400">
                    <RefreshCw className="size-6 animate-spin mx-auto mb-2" />
                    Loading tokens...
                </div>
            </Section>
        );
    }

    const activeTokens = tokens.filter((t) => t.isActive);
    const inactiveTokens = tokens.filter((t) => !t.isActive);

    return (
        <Section title="Executive Dashboard Tokens">
            <div className="p-4 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-xl mb-4">
                <div className="flex items-start gap-2">
                    <Shield className="size-5 text-amber-500 flex-shrink-0 mt-0.5" />
                    <div className="text-sm text-amber-700 dark:text-amber-400">
                        <strong>Security Note:</strong> Executive tokens grant login-less, display-only access to the Executive
                        dashboard at <code>/executive</code>. Tokens are shown <strong>only once</strong> when generated and lock to a
                        single device on first use.
                    </div>
                </div>
            </div>

            <div className="flex items-center justify-between mb-4">
                <div className="flex items-center gap-2">
                    <Key className="size-5 text-cyan-500" />
                    <h3 className="font-semibold text-slate-800 dark:text-white">Active Tokens</h3>
                    <span className="text-xs bg-cyan-100 dark:bg-cyan-900/30 text-cyan-600 dark:text-cyan-400 px-2 py-0.5 rounded-full">{activeTokens.length}</span>
                </div>
                <Button variant="primary" size="md" onClick={() => setShowForm(true)} className="bg-cyan-500 hover:bg-cyan-600 text-white text-sm font-medium">
                    <Plus className="size-4" /> Generate Token
                </Button>
            </div>

            {showForm && !generatedToken && (
                <div className="p-4 bg-slate-50 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-xl mb-4 space-y-4">
                    <h4 className="font-medium text-slate-800 dark:text-white">Generate New Executive Token</h4>
                    <div className="grid md:grid-cols-2 gap-4">
                        <div>
                            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Display Name *</label>
                            <input aria-label="Display name" type="text" value={displayName} onChange={(e) => setDisplayName(e.target.value)} placeholder="e.g., Board Room Wall" className="w-full px-3 py-2 border border-slate-200 dark:border-slate-700 rounded-lg bg-white dark:bg-slate-800 text-slate-800 dark:text-white" />
                        </div>
                        <div>
                            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Device/Location Name</label>
                            <input aria-label="Device or location name" type="text" value={deviceName} onChange={(e) => setDeviceName(e.target.value)} placeholder="e.g., Exec Suite TV" className="w-full px-3 py-2 border border-slate-200 dark:border-slate-700 rounded-lg bg-white dark:bg-slate-800 text-slate-800 dark:text-white" />
                        </div>
                        <div>
                            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Country Filter</label>
                            <select value={countryId} onChange={(e) => setCountryId(e.target.value)} className="w-full px-3 py-2 border border-slate-200 dark:border-slate-700 rounded-lg bg-white dark:bg-slate-800 text-slate-800 dark:text-white">
                                <option value="">All Countries (Global)</option>
                                {countries.map((c) => <option key={c.id} value={c.id}>{c.name}</option>)}
                            </select>
                        </div>
                        <div>
                            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Token Expiry</label>
                            <select value={expiryDays} onChange={(e) => setExpiryDays(parseInt(e.target.value))} className="w-full px-3 py-2 border border-slate-200 dark:border-slate-700 rounded-lg bg-white dark:bg-slate-800 text-slate-800 dark:text-white">
                                {EXPIRY_OPTIONS.map((opt) => <option key={opt.value} value={opt.value}>{opt.label}</option>)}
                            </select>
                        </div>
                    </div>
                    <div className="flex justify-end gap-2 pt-2">
                        <Button variant="ghost" size="md" onClick={() => setShowForm(false)} className="text-slate-600 dark:text-slate-400 hover:bg-slate-100 dark:hover:bg-slate-700">Cancel</Button>
                        <Button variant="primary" size="md" onClick={handleGenerate} disabled={!displayName.trim() || saving} className="bg-cyan-500 hover:bg-cyan-600 text-white font-medium">{saving ? 'Generating...' : 'Generate Token'}</Button>
                    </div>
                </div>
            )}

            {generatedToken && (
                <div className="p-6 bg-emerald-50 dark:bg-emerald-900/20 border border-emerald-200 dark:border-emerald-800 rounded-xl mb-4">
                    <div className="flex items-center gap-2 mb-3">
                        <Check className="size-5 text-emerald-500" />
                        <h4 className="font-semibold text-emerald-700 dark:text-emerald-400">Token Generated Successfully</h4>
                    </div>
                    <div className="p-4 bg-white dark:bg-slate-900 rounded-lg border border-emerald-300 dark:border-emerald-700 mb-3">
                        <div className="flex items-center justify-between gap-3">
                            <code className="text-lg font-mono text-slate-800 dark:text-white break-all">{generatedToken}</code>
                            <IconButton label="Copy token" variant="ghost" size="md" onClick={copyToken} className="flex-shrink-0 bg-slate-100 dark:bg-slate-800 hover:bg-slate-200 dark:hover:bg-slate-700">
                                {copied ? <Check className="size-5 text-emerald-500" /> : <Copy className="size-5 text-slate-500" />}
                            </IconButton>
                        </div>
                    </div>
                    <div className="flex items-start gap-2 text-sm text-amber-700 dark:text-amber-400 bg-amber-50 dark:bg-amber-900/30 p-3 rounded-lg">
                        <AlertTriangle className="size-4 flex-shrink-0 mt-0.5" />
                        <div><strong>Copy this token now!</strong> It will not be shown again. Enter it at <code>/executive</code> to authenticate the display.</div>
                    </div>
                    <Button variant="success" size="md" onClick={() => { setGeneratedToken(null); setShowForm(false); }} className="mt-4 w-full bg-emerald-500 hover:bg-emerald-600 text-white font-medium">I&apos;ve Copied the Token</Button>
                </div>
            )}

            {activeTokens.length === 0 ? (
                <div className="p-8 text-center border border-dashed border-slate-200 dark:border-slate-700 rounded-xl">
                    <Key className="size-8 mx-auto mb-2 text-slate-300 dark:text-slate-600" />
                    <p className="text-slate-400 text-sm">No active executive tokens</p>
                    <Button variant="ghost" size="sm" onClick={() => setShowForm(true)} className="mt-2 text-cyan-500 hover:text-cyan-600 text-sm font-medium px-0">Generate your first token</Button>
                </div>
            ) : (
                <div className="space-y-2 mb-6">
                    {activeTokens.map((token) => (
                        <div key={token.id} className="p-4 bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-xl">
                            <div className="flex items-center justify-between">
                                <div className="flex items-center gap-3">
                                    <div className="p-2 bg-cyan-100 dark:bg-cyan-900/30 rounded-lg"><LayoutDashboard className="size-5 text-cyan-500" /></div>
                                    <div>
                                        <h4 className="font-medium text-slate-800 dark:text-white">{token.displayName}</h4>
                                        <div className="flex items-center gap-3 text-xs text-slate-500 mt-0.5">
                                            <span className="font-mono bg-slate-100 dark:bg-slate-700 px-1.5 py-0.5 rounded">{token.tokenPrefix}...</span>
                                            <span className="flex items-center gap-1"><Globe className="size-3" />{getCountryName(token.countryId)}</span>
                                            {token.deviceName && <span>{token.deviceName}</span>}
                                            {token.locked && <span className="text-emerald-500">device-locked</span>}
                                        </div>
                                    </div>
                                </div>
                                <div className="flex items-center gap-4">
                                    <div className="text-right text-xs">
                                        {token.expiresIn !== null && (
                                            <div className={`flex items-center gap-1 ${token.expiresIn <= 7 ? 'text-amber-500' : 'text-slate-500'}`}>
                                                <Clock className="size-3" />{token.expiresIn > 0 ? `Expires in ${token.expiresIn} days` : 'Expires today'}
                                            </div>
                                        )}
                                        {token.lastUsedAt && <div className="text-slate-400 mt-0.5">Last used: {formatDate(token.lastUsedAt)}</div>}
                                    </div>
                                    <IconButton label="Revoke Token" variant="ghost" size="md" onClick={() => handleRevoke(token.id, token.displayName)} className="hover:bg-red-50 dark:hover:bg-red-900/20" title="Revoke Token">
                                        <Trash2 className="size-4 text-red-400" />
                                    </IconButton>
                                </div>
                            </div>
                        </div>
                    ))}
                </div>
            )}

            {inactiveTokens.length > 0 && (
                <>
                    <h4 className="font-medium text-slate-600 dark:text-slate-400 mb-2 text-sm">Revoked/Expired Tokens ({inactiveTokens.length})</h4>
                    <div className="space-y-2 opacity-60">
                        {inactiveTokens.map((token) => (
                            <div key={token.id} className="p-3 bg-slate-50 dark:bg-slate-900 border border-slate-100 dark:border-slate-800 rounded-xl">
                                <div className="flex items-center justify-between">
                                    <div className="flex items-center gap-2">
                                        <span className="line-through text-slate-500">{token.displayName}</span>
                                        <span className={`text-xs px-2 py-0.5 rounded ${token.isRevoked ? 'bg-red-100 dark:bg-red-900/30 text-red-600 dark:text-red-400' : 'bg-amber-100 dark:bg-amber-900/30 text-amber-600 dark:text-amber-400'}`}>{token.isRevoked ? 'Revoked' : 'Expired'}</span>
                                    </div>
                                    <span className="text-xs text-slate-400">{formatDate(token.createdAt)}</span>
                                </div>
                            </div>
                        ))}
                    </div>
                </>
            )}
        </Section>
    );
}
