import { useState, useEffect, useLayoutEffect, useRef } from 'react';
import {
    Dialog,
    DialogContent,
    DialogTitle,
    DialogDescription,
} from '@/components/ui/dialog';
import { ScrollArea } from '@/components/ui/scroll-area';
import { VisuallyHidden } from '@radix-ui/react-visually-hidden';
import { Button } from '@/components/ui/button';
import { Separator } from '@/components/ui/separator';
import { toast } from '@/components/ui/toast-store';
import { apiFetch } from '@/lib/api';
import { SENCHO_SETTINGS_CHANGED } from '@/lib/events';
import type { SenchoSettingsChangedDetail } from '@/lib/events';
import {
    Shield, Activity, Bell, Code, Server, Package,
    Info, Crown, Webhook, Users, Zap, Database, LifeBuoy, Lock, Tag, Route,
} from 'lucide-react';
import { NodeManager } from './NodeManager';
import { useNodes } from '@/context/NodeContext';
import { useAuth } from '@/context/AuthContext';
import { useLicense } from '@/context/LicenseContext';
import { SSOSection } from './SSOSection';
import { ApiTokensSection } from './ApiTokensSection';
import { RegistriesSection } from './RegistriesSection';
import {
    AccountSection,
    LicenseSection,
    UsersSection,
    SystemSection,
    NotificationsSection,
    NotificationRoutingSection,
    WebhooksSection,
    DeveloperSection,
    AppStoreSection,
    SupportSection,
    AboutSection,
    LabelsSection,
    DEFAULT_SETTINGS,
} from './settings';
import type { PatchableSettings, SectionId } from './settings';

const GLOBAL_ONLY_SECTIONS: ReadonlySet<SectionId> = new Set<SectionId>([
    'account', 'license', 'users', 'sso', 'api-tokens', 'registries',
    'labels', 'notifications', 'notification-routing', 'webhooks', 'nodes', 'appstore',
]);

interface SettingsModalProps {
    isOpen: boolean;
    onClose: () => void;
    initialSection?: SectionId;
}

export function SettingsModal({ isOpen, onClose, initialSection }: SettingsModalProps) {
    const { activeNode } = useNodes();
    const { isAdmin } = useAuth();
    const { license, isPaid } = useLicense();
    const isRemote = activeNode?.type === 'remote';
    const [activeSection, setActiveSection] = useState<SectionId>(initialSection || 'account');

    const contentViewportRef = useRef<HTMLDivElement | null>(null);
    const scrollPositionsRef = useRef<Partial<Record<SectionId, number>>>({});

    const switchSection = (next: SectionId) => {
        if (contentViewportRef.current) {
            scrollPositionsRef.current[activeSection] = contentViewportRef.current.scrollTop;
        }
        setActiveSection(next);
    };

    useLayoutEffect(() => {
        if (contentViewportRef.current) {
            contentViewportRef.current.scrollTop = scrollPositionsRef.current[activeSection] ?? 0;
        }
    }, [activeSection]);

    useEffect(() => {
        if (isOpen && initialSection) setActiveSection(initialSection);
    }, [isOpen, initialSection]);

    // Remote nodes don't expose global-only sections, so bounce to a node-scoped one.
    useEffect(() => {
        if (isRemote && GLOBAL_ONLY_SECTIONS.has(activeSection)) {
            switchSection('system');
        }
    }, [isRemote]); // eslint-disable-line react-hooks/exhaustive-deps

    // Auth State
    const [authData, setAuthData] = useState({ oldPassword: '', newPassword: '', confirmPassword: '' });
    const [isSavingPassword, setIsSavingPassword] = useState(false);

    // Settings state
    const [settings, setSettings] = useState<PatchableSettings>({ ...DEFAULT_SETTINGS });
    const serverSettingsRef = useRef<PatchableSettings>({ ...DEFAULT_SETTINGS });
    const [isSettingsLoading, setIsSettingsLoading] = useState(false);
    const [isSavingSystem, setIsSavingSystem] = useState(false);
    const [isSavingDeveloper, setIsSavingDeveloper] = useState(false);

    // Unsaved changes indicators
    const hasSystemChanges =
        settings.host_cpu_limit !== serverSettingsRef.current.host_cpu_limit ||
        settings.host_ram_limit !== serverSettingsRef.current.host_ram_limit ||
        settings.host_disk_limit !== serverSettingsRef.current.host_disk_limit ||
        settings.docker_janitor_gb !== serverSettingsRef.current.docker_janitor_gb ||
        settings.global_crash !== serverSettingsRef.current.global_crash;

    const hasDeveloperChanges =
        settings.developer_mode !== serverSettingsRef.current.developer_mode ||
        settings.global_logs_refresh !== serverSettingsRef.current.global_logs_refresh ||
        settings.metrics_retention_hours !== serverSettingsRef.current.metrics_retention_hours ||
        settings.log_retention_days !== serverSettingsRef.current.log_retention_days ||
        settings.audit_retention_days !== serverSettingsRef.current.audit_retention_days;

    useEffect(() => {
        if (isOpen) fetchSettings();
    }, [isOpen, activeNode?.id]); // eslint-disable-line react-hooks/exhaustive-deps

    const fetchSettings = async () => {
        setIsSettingsLoading(true);
        try {
            const nodeRes = await apiFetch('/settings');
            const localRes = isRemote ? await apiFetch('/settings', { localOnly: true }) : nodeRes;
            const nodeData: Record<string, string> = nodeRes.ok ? await nodeRes.json() : {};
            const localData: Record<string, string> = (isRemote && localRes.ok)
                ? await localRes.json()
                : nodeData;

            const safe: PatchableSettings = {
                host_cpu_limit: nodeData.host_cpu_limit ?? DEFAULT_SETTINGS.host_cpu_limit,
                host_ram_limit: nodeData.host_ram_limit ?? DEFAULT_SETTINGS.host_ram_limit,
                host_disk_limit: nodeData.host_disk_limit ?? DEFAULT_SETTINGS.host_disk_limit,
                docker_janitor_gb: nodeData.docker_janitor_gb ?? DEFAULT_SETTINGS.docker_janitor_gb,
                global_crash: (nodeData.global_crash as '0' | '1') ?? DEFAULT_SETTINGS.global_crash,
                template_registry_url: nodeData.template_registry_url ?? '',
                global_logs_refresh: (localData.global_logs_refresh as '1' | '3' | '5' | '10') ?? DEFAULT_SETTINGS.global_logs_refresh,
                developer_mode: (localData.developer_mode as '0' | '1') ?? DEFAULT_SETTINGS.developer_mode,
                metrics_retention_hours: localData.metrics_retention_hours ?? DEFAULT_SETTINGS.metrics_retention_hours,
                log_retention_days: localData.log_retention_days ?? DEFAULT_SETTINGS.log_retention_days,
                audit_retention_days: localData.audit_retention_days ?? DEFAULT_SETTINGS.audit_retention_days,
            };
            setSettings(safe);
            serverSettingsRef.current = { ...safe };
        } catch (e) {
            console.error('Failed to fetch settings', e);
        } finally {
            setIsSettingsLoading(false);
        }
    };

    const handleSettingChange = <K extends keyof PatchableSettings>(key: K, value: PatchableSettings[K]) => {
        setSettings(prev => ({ ...prev, [key]: value }));
    };

    const patchSettings = async (payload: PatchableSettings, setLoading: (v: boolean) => void, localOnly = false): Promise<boolean> => {
        setLoading(true);
        try {
            const res = await apiFetch('/settings', {
                method: 'PATCH',
                body: JSON.stringify(payload),
                localOnly,
            });
            if (!res.ok) {
                const err = await res.json().catch(() => ({}));
                toast.error(err?.error || err?.message || 'Failed to save settings.');
                return false;
            }
            serverSettingsRef.current = { ...serverSettingsRef.current, ...payload };
            return true;
        } catch (e: unknown) {
            toast.error((e as Error)?.message || 'Something went wrong.');
            return false;
        } finally {
            setLoading(false);
        }
    };

    const saveSystemSettings = async () => {
        const ok = await patchSettings({
            host_cpu_limit: settings.host_cpu_limit,
            host_ram_limit: settings.host_ram_limit,
            host_disk_limit: settings.host_disk_limit,
            docker_janitor_gb: settings.docker_janitor_gb,
            global_crash: settings.global_crash,
        }, setIsSavingSystem);
        if (ok) toast.success('System limits saved.');
    };

    const saveDeveloperSettings = async () => {
        const payload = {
            developer_mode: settings.developer_mode,
            global_logs_refresh: settings.global_logs_refresh,
            metrics_retention_hours: settings.metrics_retention_hours,
            log_retention_days: settings.log_retention_days,
            audit_retention_days: settings.audit_retention_days,
        };
        const ok = await patchSettings(payload, setIsSavingDeveloper, true);
        if (ok) {
            toast.success('Developer settings saved.');
            window.dispatchEvent(new CustomEvent<SenchoSettingsChangedDetail>(SENCHO_SETTINGS_CHANGED, {
                detail: { changedKeys: Object.keys(payload) },
            }));
        }
    };

    const handlePasswordChange = async () => {
        if (!authData.oldPassword || !authData.newPassword || !authData.confirmPassword) {
            toast.error('All fields are required');
            return;
        }
        if (authData.newPassword !== authData.confirmPassword) {
            toast.error('New passwords do not match');
            return;
        }
        if (authData.newPassword.length < 8) {
            toast.error('New password must be at least 8 characters');
            return;
        }
        setIsSavingPassword(true);
        try {
            const res = await apiFetch('/auth/password', {
                method: 'PUT',
                body: JSON.stringify({ oldPassword: authData.oldPassword, newPassword: authData.newPassword }),
            });
            if (res.ok) {
                toast.success('Password updated successfully');
                setAuthData({ oldPassword: '', newPassword: '', confirmPassword: '' });
            } else {
                const data = await res.json().catch(() => ({}));
                toast.error(data?.error || 'Failed to update password');
            }
        } catch (e: unknown) {
            toast.error((e as Error)?.message || 'Network error during password change');
        } finally {
            setIsSavingPassword(false);
        }
    };

    const handleRegistrySaved = (key: keyof PatchableSettings, value: string) => {
        serverSettingsRef.current = { ...serverSettingsRef.current, [key]: value };
    };

    // --- Nav items ---
    const NavButton = ({ section, icon, label, showDot, locked }: {
        section: SectionId;
        icon: React.ReactNode;
        label: string;
        showDot?: boolean;
        locked?: boolean;
    }) => (
        <Button
            variant={activeSection === section ? 'secondary' : 'ghost'}
            className="w-full justify-start font-medium relative"
            onClick={() => switchSection(section)}
        >
            {icon}
            {label}
            {locked && <Lock className="w-3 h-3 ml-auto text-muted-foreground/50" />}
            {showDot && (
                <span className="absolute right-2 top-1/2 -translate-y-1/2 w-1.5 h-1.5 rounded-full bg-amber-400" />
            )}
        </Button>
    );

    // --- Section rendering ---
    const renderSection = () => {
        switch (activeSection) {
            case 'account':
                return (
                    <AccountSection
                        authData={authData}
                        onAuthDataChange={setAuthData}
                        onPasswordChange={handlePasswordChange}
                        isSaving={isSavingPassword}
                    />
                );
            case 'license':
                return <LicenseSection />;
            case 'users':
                return <UsersSection />;
            case 'sso':
                return <SSOSection />;
            case 'api-tokens':
                return <ApiTokensSection />;
            case 'registries':
                return <RegistriesSection />;
            case 'labels':
                return <LabelsSection />;
            case 'system':
                return (
                    <SystemSection
                        settings={settings}
                        onSettingChange={handleSettingChange}
                        onSave={saveSystemSettings}
                        isSaving={isSavingSystem}
                        isLoading={isSettingsLoading}
                        isRemote={isRemote}
                        activeNodeName={activeNode?.name}
                    />
                );
            case 'notifications':
                return <NotificationsSection />;
            case 'notification-routing':
                return <NotificationRoutingSection />;
            case 'webhooks':
                return <WebhooksSection isPaid={isPaid} />;
            case 'developer':
                return (
                    <DeveloperSection
                        settings={settings}
                        onSettingChange={handleSettingChange}
                        onSave={saveDeveloperSettings}
                        isSaving={isSavingDeveloper}
                        isLoading={isSettingsLoading}
                        isRemote={isRemote}
                    />
                );
            case 'nodes':
                return <NodeManager />;
            case 'appstore':
                return (
                    <AppStoreSection
                        settings={settings}
                        onSettingChange={handleSettingChange}
                        isLoading={isSettingsLoading}
                        onSaved={handleRegistrySaved}
                    />
                );
            case 'support':
                return <SupportSection />;
            case 'about':
                return <AboutSection />;
        }
    };

    const isAdmiral = isPaid && license?.variant === 'admiral';

    return (
        <Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
            <DialogContent className="sm:max-w-[900px] h-[min(650px,85vh)] flex p-0 font-sans shadow-lg bg-background border-border overflow-hidden gap-0">
                <VisuallyHidden><DialogTitle>Settings Hub</DialogTitle></VisuallyHidden>
                <VisuallyHidden><DialogDescription>Configure Sencho settings</DialogDescription></VisuallyHidden>

                {/* Sidebar */}
                <div className="w-[200px] bg-glass border-r border-glass-border flex flex-col p-4 shrink-0 min-h-0">
                    <div className="font-medium text-lg mb-1 text-foreground tracking-tight">Settings Hub</div>
                    {isRemote ? (
                        <div className="text-xs text-muted-foreground mb-5 truncate">{activeNode!.name}</div>
                    ) : (
                        <div className="mb-5" />
                    )}
                    <ScrollArea className="flex-1 -mr-2 pr-2">
                        <nav className="space-y-1.5 flex flex-col">
                        {/* Account / License */}
                        {!isRemote && (
                            <NavButton section="account" icon={<Shield className="w-4 h-4 mr-2" />} label="Account" />
                        )}
                        {!isRemote && (
                            <NavButton section="license" icon={<Crown className="w-4 h-4 mr-2" />} label="License" />
                        )}

                        {!isRemote && <Separator className="my-1.5" />}

                        {/* Users / SSO / API Tokens / Registries */}
                        {!isRemote && isAdmin && (
                            <NavButton section="users" icon={<Users className="w-4 h-4 mr-2" />} label="Users" locked={!isPaid} />
                        )}
                        {!isRemote && isAdmin && (
                            <NavButton section="sso" icon={<Shield className="w-4 h-4 mr-2" />} label="SSO" locked={!isAdmiral} />
                        )}
                        {!isRemote && isAdmin && (
                            <NavButton section="api-tokens" icon={<Zap className="w-4 h-4 mr-2" />} label="API Tokens" locked={!isAdmiral} />
                        )}
                        {!isRemote && isAdmin && (
                            <NavButton section="registries" icon={<Database className="w-4 h-4 mr-2" />} label="Registries" locked={!isAdmiral} />
                        )}
                        {!isRemote && (
                            <NavButton section="labels" icon={<Tag className="w-4 h-4 mr-2" />} label="Labels" locked={!isPaid} />
                        )}

                        {!isRemote && isAdmin && <Separator className="my-1.5" />}

                        {/* System / Notifications / Webhooks / Developer */}
                        <NavButton
                            section="system"
                            icon={<Activity className="w-4 h-4 mr-2" />}
                            label="System Limits"
                            showDot={hasSystemChanges}
                        />
                        <NavButton section="notifications" icon={<Bell className="w-4 h-4 mr-2" />} label="Notifications" />
                        {!isRemote && isAdmin && (
                            <NavButton section="notification-routing" icon={<Route className="w-4 h-4 mr-2" />} label="Routing" locked={!isAdmiral} />
                        )}
                        {!isRemote && (
                            <NavButton section="webhooks" icon={<Webhook className="w-4 h-4 mr-2" />} label="Webhooks" locked={!isPaid} />
                        )}
                        <NavButton
                            section="developer"
                            icon={<Code className="w-4 h-4 mr-2" />}
                            label="Developer"
                            showDot={hasDeveloperChanges}
                        />

                        <Separator className="my-1.5" />

                        {/* Nodes / App Store */}
                        {!isRemote && (
                            <NavButton section="nodes" icon={<Server className="w-4 h-4 mr-2" />} label="Nodes" />
                        )}
                        {!isRemote && (
                            <NavButton section="appstore" icon={<Package className="w-4 h-4 mr-2" />} label="App Store" />
                        )}

                        <Separator className="my-1.5" />

                        {/* Support / About */}
                        <NavButton section="support" icon={<LifeBuoy className="w-4 h-4 mr-2" />} label="Support" />
                        <NavButton section="about" icon={<Info className="w-4 h-4 mr-2" />} label="About" />
                        </nav>
                    </ScrollArea>
                </div>

                {/* Main Content Area */}
                <ScrollArea viewportRef={contentViewportRef} className="flex-1">
                    <div className="p-6 flex flex-col gap-6">
                        {renderSection()}
                    </div>
                </ScrollArea>
            </DialogContent>
        </Dialog>
    );
}
