import { useEffect, useMemo, useState } from 'react';
import { useNavigate, useOutletContext } from 'react-router-dom';
import {
  Input,
  Switch,
  Button,
  Alert,
  Space,
  Tag,
  Modal,
  Tooltip,
  Select,
  Badge,
  message,
  Spin,
  Form,
} from 'antd';
import {
  SaveOutlined,
  LinkOutlined,
  ArrowUpOutlined,
  ArrowDownOutlined,
  DeleteOutlined,
  PlusOutlined,
  FolderOutlined,
  FolderAddOutlined,
  ExclamationCircleOutlined,
} from '@ant-design/icons';
import { useSettingsStore } from '@/stores/settings.store';
import { useMobile } from '@/hooks/useMobile';
import type { AppOutletContext } from '@/components/AppLayout';
import type { NavItem } from '@/types/api';
import {
  DEFAULT_NAV_ITEMS,
  ICON_MAP,
  mergeNavDefaults,
  buildFeatureFlags,
  flagPasses,
} from '@/lib/nav-defaults';

export default function NavigationSettingsPage() {
  const { setPageHeader } = useOutletContext<AppOutletContext>();
  const { isMobile } = useMobile();
  const { settings, loading, fetchAdminSettings, updateSettings } = useSettingsStore();

  const [navItems, setNavItems] = useState<NavItem[]>(DEFAULT_NAV_ITEMS);
  const [dirty, setDirty] = useState(false);
  const [saving, setSaving] = useState(false);
  const [customLinkModalOpen, setCustomLinkModalOpen] = useState(false);
  const [customLinkLabel, setCustomLinkLabel] = useState('');
  const [customLinkPath, setCustomLinkPath] = useState('');

  const navigate = useNavigate();
  const featureFlags = useMemo(() => buildFeatureFlags(settings), [settings]);

  const isFeatureFlagDisabled = (item: NavItem): boolean => {
    if (!item.featureFlag) return false;
    return !flagPasses(item.featureFlag, featureFlags);
  };

  // Check if any item has a disabled feature flag (for warning banner)
  const hasDisabledFlags = useMemo(() => {
    return navItems.some(item => {
      if (isFeatureFlagDisabled(item)) return true;
      return item.children?.some(c => isFeatureFlagDisabled(c)) ?? false;
    });
  }, [navItems, featureFlags]);

  useEffect(() => {
    setPageHeader({ title: 'Navigation' });
    return () => setPageHeader(null);
  }, [setPageHeader]);

  useEffect(() => {
    fetchAdminSettings();
  }, [fetchAdminSettings]);

  useEffect(() => {
    if (settings?.navConfig?.items) {
      setNavItems(mergeNavDefaults(settings.navConfig.items));
    }
  }, [settings]);

  const handleSave = async () => {
    setSaving(true);
    try {
      await updateSettings({ navConfig: { items: navItems } });
      setDirty(false);
      message.success('Navigation saved');
    } catch {
      message.error('Failed to save navigation');
    } finally {
      setSaving(false);
    }
  };

  // --- Toggle enable/disable (works for top-level and children) ---
  const toggleNavItem = (itemId: string, enabled: boolean) => {
    setNavItems(prev => prev.map(item => {
      if (item.id === itemId) return { ...item, enabled };
      if (item.children) {
        const children = item.children.map(c => c.id === itemId ? { ...c, enabled } : c);
        return { ...item, children };
      }
      return item;
    }));
    setDirty(true);
  };

  // --- Reorder: scoped to sibling context ---
  const moveNavItem = (itemId: string, direction: 'up' | 'down') => {
    setNavItems(prev => {
      // Check if item is top-level
      const topIdx = prev.findIndex(i => i.id === itemId);
      if (topIdx >= 0) {
        const sorted = [...prev].sort((a, b) => a.order - b.order);
        const idx = sorted.findIndex(i => i.id === itemId);
        const swapIdx = direction === 'up' ? idx - 1 : idx + 1;
        if (swapIdx < 0 || swapIdx >= sorted.length) return prev;
        const tempOrder = sorted[idx]!.order;
        sorted[idx] = { ...sorted[idx]!, order: sorted[swapIdx]!.order };
        sorted[swapIdx] = { ...sorted[swapIdx]!, order: tempOrder };
        return sorted.sort((a, b) => a.order - b.order);
      }
      // Check children
      return prev.map(item => {
        if (!item.children) return item;
        const childIdx = item.children.findIndex(c => c.id === itemId);
        if (childIdx < 0) return item;
        const sorted = [...item.children].sort((a, b) => a.order - b.order);
        const idx = sorted.findIndex(c => c.id === itemId);
        const swapIdx = direction === 'up' ? idx - 1 : idx + 1;
        if (swapIdx < 0 || swapIdx >= sorted.length) return item;
        const tempOrder = sorted[idx]!.order;
        sorted[idx] = { ...sorted[idx]!, order: sorted[swapIdx]!.order };
        sorted[swapIdx] = { ...sorted[swapIdx]!, order: tempOrder };
        return { ...item, children: sorted.sort((a, b) => a.order - b.order) };
      });
    });
    setDirty(true);
  };

  // --- Update a field on any item (top-level or child) ---
  const updateNavItemField = (itemId: string, field: 'label' | 'path', value: string) => {
    setNavItems(prev => prev.map(item => {
      if (item.id === itemId) return { ...item, [field]: value };
      if (item.children) {
        const children = item.children.map(c => c.id === itemId ? { ...c, [field]: value } : c);
        return { ...item, children };
      }
      return item;
    }));
    setDirty(true);
  };

  // --- Delete an item ---
  const deleteNavItem = (itemId: string) => {
    setNavItems(prev => {
      // If it's a group, move children to top-level first
      const group = prev.find(i => i.id === itemId && i.type === 'group');
      if (group && group.children) {
        const maxOrder = prev.reduce((max, i) => Math.max(max, i.order), -1);
        const promotedChildren = group.children.map((c, idx) => ({ ...c, order: maxOrder + 1 + idx }));
        return [...prev.filter(i => i.id !== itemId), ...promotedChildren];
      }
      // Remove from top-level
      const withoutTop = prev.filter(i => i.id !== itemId);
      if (withoutTop.length < prev.length) return withoutTop;
      // Remove from children
      return prev.map(item => {
        if (!item.children) return item;
        const filtered = item.children.filter(c => c.id !== itemId);
        return filtered.length !== item.children.length ? { ...item, children: filtered } : item;
      });
    });
    setDirty(true);
  };

  // --- Add custom link ---
  const addCustomNavLink = () => {
    if (!customLinkLabel.trim() || !customLinkPath.trim()) return;
    const maxOrder = navItems.reduce((max, item) => Math.max(max, item.order), -1);
    setNavItems(prev => [...prev, {
      id: `custom-${Date.now()}`,
      label: customLinkLabel.trim(),
      path: customLinkPath.trim(),
      icon: 'LinkOutlined',
      enabled: true,
      order: maxOrder + 1,
      type: 'custom',
      external: customLinkPath.trim().startsWith('http'),
    }]);
    setCustomLinkLabel('');
    setCustomLinkPath('');
    setCustomLinkModalOpen(false);
    setDirty(true);
  };

  // --- Add group ---
  const addGroup = () => {
    const maxOrder = navItems.reduce((max, item) => Math.max(max, item.order), -1);
    setNavItems(prev => [...prev, {
      id: `group-${Date.now()}`,
      label: 'New Group',
      path: '',
      icon: 'FolderOutlined',
      enabled: true,
      order: maxOrder + 1,
      type: 'group',
      children: [],
    }]);
    setDirty(true);
  };

  // --- Move item to/from group ---
  const moveItemToGroup = (itemId: string, targetGroupId: string | null) => {
    setNavItems(prev => {
      // Extract item from wherever it currently is
      let extractedItem: NavItem | null = null;
      let items = prev.map(item => {
        if (item.id === itemId) {
          extractedItem = item;
          return null; // Mark for removal
        }
        if (item.children) {
          const child = item.children.find(c => c.id === itemId);
          if (child) {
            extractedItem = child;
            return { ...item, children: item.children.filter(c => c.id !== itemId) };
          }
        }
        return item;
      }).filter(Boolean) as NavItem[];

      if (!extractedItem) return prev;
      const extracted: NavItem = extractedItem;

      if (targetGroupId === null) {
        // Move to top level
        const maxOrder = items.reduce((max, i) => Math.max(max, i.order), -1);
        return [...items, { ...extracted, order: maxOrder + 1 }];
      }

      // Move into target group
      return items.map(item => {
        if (item.id === targetGroupId) {
          const maxChildOrder = (item.children || []).reduce((max, c) => Math.max(max, c.order), -1);
          return {
            ...item,
            children: [...(item.children || []), { ...extracted, order: maxChildOrder + 1 }],
          };
        }
        return item;
      });
    });
    setDirty(true);
  };

  // Get all groups for the "Move to Group" dropdown
  const groups = navItems.filter(i => i.type === 'group');

  if (loading) {
    return (
      <div style={{ textAlign: 'center', padding: 80 }}>
        <Spin size="large" />
      </div>
    );
  }

  // Helper to find which group an item belongs to (null = top-level)
  const findParentGroupId = (itemId: string): string | null => {
    for (const item of navItems) {
      if (item.children?.some(c => c.id === itemId)) return item.id;
    }
    return null;
  };

  const renderItemRow = (item: NavItem, _idx: number, siblings: NavItem[], indent: boolean, parentFlagDisabled = false) => {
    const isGroup = item.type === 'group';
    const sorted = [...siblings].sort((a, b) => a.order - b.order);
    const sortedIdx = sorted.findIndex(i => i.id === item.id);
    const parentGroupId = indent ? findParentGroupId(item.id) : null;
    const ownFlagDisabled = isFeatureFlagDisabled(item);
    const flagDisabled = ownFlagDisabled || parentFlagDisabled;

    return (
      <div
        key={item.id}
        style={{
          display: 'grid',
          gridTemplateColumns: indent
            ? '40px 32px 1fr 1fr auto auto 90px'
            : '40px 32px 1fr 1.5fr auto auto 90px',
          gap: 8,
          alignItems: 'center',
          padding: '8px 12px',
          paddingLeft: indent ? 52 : 12,
          minWidth: 600,
          background: isGroup
            ? 'rgba(100,150,255,0.06)'
            : item.enabled ? 'rgba(255,255,255,0.04)' : 'rgba(255,255,255,0.01)',
          borderRadius: 6,
          border: isGroup
            ? '1px solid rgba(100,150,255,0.15)'
            : '1px solid rgba(255,255,255,0.08)',
          borderLeft: flagDisabled
            ? '3px dashed rgba(250,173,20,0.6)'
            : indent ? '3px solid rgba(100,150,255,0.3)' : undefined,
          opacity: item.enabled ? (flagDisabled ? 0.55 : 1) : 0.5,
        }}
      >
        <Switch
          size="small"
          checked={item.enabled}
          onChange={(checked) => toggleNavItem(item.id, checked)}
        />
        <span style={{ fontSize: 16, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          {isGroup ? <FolderOutlined /> : (ICON_MAP[item.icon] || <LinkOutlined />)}
        </span>
        <Input
          size="small"
          value={item.label}
          onChange={(e) => updateNavItemField(item.id, 'label', e.target.value)}
        />
        {isGroup ? (
          <Badge count={item.children?.length ?? 0} size="small" offset={[8, 0]} color="blue">
            <span style={{ fontSize: 12, color: 'rgba(255,255,255,0.45)', fontStyle: 'italic' }}>Group — {item.children?.length ?? 0} items</span>
          </Badge>
        ) : (
          <Tooltip title={item.path.startsWith('$') ? 'Auto-resolved based on environment' : undefined}>
            <Input
              size="small"
              value={item.path}
              onChange={(e) => updateNavItemField(item.id, 'path', e.target.value)}
              disabled={item.path.startsWith('$') || isGroup}
              style={{ fontFamily: 'monospace', fontSize: 12 }}
            />
          </Tooltip>
        )}
        <Space size={2}>
          <Tooltip title="Move up">
            <Button
              type="text"
              size="small"
              icon={<ArrowUpOutlined />}
              onClick={() => moveNavItem(item.id, 'up')}
              disabled={sortedIdx === 0}
              style={{ width: 24, height: 24 }}
            />
          </Tooltip>
          <Tooltip title="Move down">
            <Button
              type="text"
              size="small"
              icon={<ArrowDownOutlined />}
              onClick={() => moveNavItem(item.id, 'down')}
              disabled={sortedIdx === sorted.length - 1}
              style={{ width: 24, height: 24 }}
            />
          </Tooltip>
          {(item.type === 'custom' || item.type === 'group') && (
            <Tooltip title={isGroup ? 'Delete group (children move to top level)' : 'Delete'}>
              <Button
                type="text"
                size="small"
                danger
                icon={<DeleteOutlined />}
                onClick={() => deleteNavItem(item.id)}
                style={{ width: 24, height: 24 }}
              />
            </Tooltip>
          )}
        </Space>
        {/* Move to Group dropdown — only for non-group items */}
        {!isGroup ? (
          <Select
            size="small"
            value={parentGroupId ?? '__top__'}
            onChange={(val) => moveItemToGroup(item.id, val === '__top__' ? null : val)}
            style={{ width: 90, fontSize: 11 }}
            popupMatchSelectWidth={false}
          >
            <Select.Option value="__top__">(Top Level)</Select.Option>
            {groups.map(g => (
              <Select.Option key={g.id} value={g.id}>{g.label}</Select.Option>
            ))}
          </Select>
        ) : (
          <div style={{ textAlign: 'right' }}>
            {item.featureFlag ? (
              ownFlagDisabled ? (
                <Tooltip title={<span>Feature disabled in Settings. <a onClick={() => navigate('/app/settings', { state: { tab: 'features' } })} style={{ color: '#69b1ff', cursor: 'pointer' }}>Feature Toggles</a></span>}>
                  <Tag color="orange" style={{ margin: 0, fontSize: 10, cursor: 'help' }}>
                    <ExclamationCircleOutlined style={{ marginRight: 3 }} />
                    {item.featureFlag.replace('enable', '')} Off
                  </Tag>
                </Tooltip>
              ) : (
                <Tooltip title={`Controlled by ${item.featureFlag}`}>
                  <Tag color="cyan" style={{ margin: 0, fontSize: 10 }}>
                    {item.featureFlag.replace('enable', '')}
                  </Tag>
                </Tooltip>
              )
            ) : (
              <Tag color="geekblue" style={{ margin: 0, fontSize: 10 }}>group</Tag>
            )}
          </div>
        )}
        {/* Feature flag tag for non-group items */}
        {!isGroup && item.featureFlag ? (
          <div style={{ textAlign: 'right' }}>
            {ownFlagDisabled ? (
              <Tooltip title={<span>Feature disabled in Settings. <a onClick={() => navigate('/app/settings', { state: { tab: 'features' } })} style={{ color: '#69b1ff', cursor: 'pointer' }}>Feature Toggles</a></span>}>
                <Tag color="orange" style={{ margin: 0, fontSize: 10, cursor: 'help' }}>
                  <ExclamationCircleOutlined style={{ marginRight: 3 }} />
                  {item.featureFlag.replace('enable', '')} Off
                </Tag>
              </Tooltip>
            ) : (
              <Tooltip title={`Controlled by ${item.featureFlag}`}>
                <Tag color="cyan" style={{ margin: 0, fontSize: 10 }}>
                  {item.featureFlag.replace('enable', '')}
                </Tag>
              </Tooltip>
            )}
          </div>
        ) : !isGroup ? (
          <div />
        ) : null}
      </div>
    );
  };

  const sorted = [...navItems].sort((a, b) => a.order - b.order);

  return (
    <div style={{ maxWidth: isMobile ? undefined : 800 }}>
      <Alert
        type="info"
        message="Configure the navigation bar shown on all public pages, the admin header, Gancio events page, and MkDocs site. Groups appear as dropdowns on desktop and collapsible sections on mobile."
        showIcon
        style={{ marginBottom: hasDisabledFlags ? 12 : 24 }}
      />
      {hasDisabledFlags && (
        <Alert
          type="warning"
          showIcon
          message={
            <span>
              Some nav items have their feature disabled in Settings.
              Items with <Tag color="orange" style={{ margin: '0 4px', fontSize: 10 }}><ExclamationCircleOutlined style={{ marginRight: 3 }} />Off</Tag>
              won't appear in public navigation until the feature is enabled.{' '}
              <Button type="link" size="small" style={{ padding: 0 }} onClick={() => navigate('/app/settings', { state: { tab: 'features' } })}>
                Feature Toggles
              </Button>
            </span>
          }
          style={{ marginBottom: 24 }}
        />
      )}

      <div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginBottom: 16, overflowX: isMobile ? 'auto' : undefined, WebkitOverflowScrolling: 'touch' as any }}>
        {sorted.map((item, idx) => (
          <div key={item.id}>
            {renderItemRow(item, idx, sorted, false)}
            {/* Render children indented below their group */}
            {item.type === 'group' && item.children && [...item.children].sort((a, b) => a.order - b.order).map((child, childIdx) =>
              renderItemRow(child, childIdx, item.children!, true, isFeatureFlagDisabled(item))
            )}
          </div>
        ))}
      </div>

      <Space wrap>
        <Button
          icon={<PlusOutlined />}
          onClick={() => setCustomLinkModalOpen(true)}
        >
          {!isMobile && 'Add Custom Link'}
        </Button>
        <Button
          icon={<FolderAddOutlined />}
          onClick={addGroup}
        >
          {!isMobile && 'Add Group'}
        </Button>
      </Space>

      <div style={{ marginTop: 24 }}>
        <Button type="primary" icon={<SaveOutlined />} size="large" onClick={handleSave} loading={saving} disabled={!dirty}>
          Save Navigation
        </Button>
      </div>

      <Modal
        title="Add Custom Link"
        open={customLinkModalOpen}
        onOk={addCustomNavLink}
        onCancel={() => setCustomLinkModalOpen(false)}
        okText="Add"
        okButtonProps={{ disabled: !customLinkLabel.trim() || !customLinkPath.trim() }}
        destroyOnHidden
      >
        <Form layout="vertical" size="small">
          <Form.Item label="Label" required>
            <Input
              value={customLinkLabel}
              onChange={(e) => setCustomLinkLabel(e.target.value)}
              placeholder="e.g. Blog"
              autoFocus
            />
          </Form.Item>
          <Form.Item label="Path or URL" required>
            <Input
              value={customLinkPath}
              onChange={(e) => setCustomLinkPath(e.target.value)}
              placeholder="e.g. /blog or https://example.com"
            />
          </Form.Item>
        </Form>
      </Modal>
    </div>
  );
}
