'use client';

import { useState, useEffect, useCallback, useRef } from 'react';
import { Stack, Text, Group, Box, Button, ActionIcon, Tooltip } from '@tidbcloud/uikit';
import { isPreparedSource, useWorkspace, WorkspaceFile } from '@/lib/workspace';
import { fetchWithAuth, getToken } from '@/lib/auth';
import { useIssuePreparation } from '@/lib/useIssuePreparation';
import { fetchEnabledSkills, type Skill } from '@/lib/skills';
import { useTranslation } from '@/lib/i18n';
import AddSourceModal from './AddSourceModal';
import FileTree, { collectDirectoryPaths } from './FileTree';
import SourceCard from './SourceCard';
import { resolveSourcesInventory, type InventoryAction, type InventoryItem } from './inventory';

interface SourcesPanelProps {
  isOwner?: boolean;
  collapsed?: boolean;
  onToggleCollapsed?: () => void;
  onOpenSkillHub?: () => void;
}

type TabKey = 'overview' | 'integrated_data' | 'files';

const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL ?? '';

function countFiles(files: WorkspaceFile[]): number {
  return files.reduce((sum, file) => (
    sum + (file.type === 'file' ? 1 : 0) + (file.children ? countFiles(file.children) : 0)
  ), 0);
}

export default function SourcesPanel({ isOwner = true, collapsed = false, onToggleCollapsed, onOpenSkillHub }: SourcesPanelProps) {
  const { t } = useTranslation();
  const {
    sources,
    setSelectedSourceId,
    openFilePath,
    setOpenFilePath,
    workspaceId,
    skillsRefreshTrigger,
    filesRefreshTrigger,
    triggerFilesRefresh,
  } = useWorkspace();
  const [showAddModal, setShowAddModal] = useState(false);
  const [activeTab, setActiveTab] = useState<TabKey>('overview');
  const [fileTree, setFileTree] = useState<WorkspaceFile[]>([]);
  const [fileTreeLoading, setFileTreeLoading] = useState(false);
  const [expandedDirPaths, setExpandedDirPaths] = useState<Set<string>>(() => new Set());
  const didSeedRootDirs = useRef(false);
  const [enabledSkills, setEnabledSkills] = useState<Skill[]>([]);
  const preparedSources = sources.filter(isPreparedSource);
  const hasPreparedSources = preparedSources.length > 0;
  const visibleTabs: TabKey[] = hasPreparedSources ? ['files', 'integrated_data'] : ['overview', 'files', 'integrated_data'];
  const activePanelTab: TabKey = hasPreparedSources && activeTab === 'overview' ? 'files' : activeTab;

  // Fetch enabled skills
  const loadEnabledSkills = useCallback(() => {
    if (!workspaceId) return;

    const token = getToken();
    if (!token) return;

    fetchEnabledSkills(workspaceId, token)
      .then(skills => {
        setEnabledSkills(skills);
      })
      .catch(err => {
        console.warn('Failed to load enabled skills:', err);
      });
  }, [workspaceId]);

  useEffect(() => {
    loadEnabledSkills();
  }, [loadEnabledSkills, skillsRefreshTrigger]);

  const refreshFileTree = useCallback((opts?: { showLoading?: boolean }) => {
    if (!workspaceId) return;
    // Only show full-panel "Loading files…" on first load (empty tree). Poll / background refresh stays silent.
    const showLoading = opts?.showLoading ?? fileTree.length === 0;
    if (showLoading) setFileTreeLoading(true);
    fetchWithAuth(`${API_BASE_URL}/api/workspace/${workspaceId}/files`, { cache: 'no-store' })
      .then(r => r.ok ? r.json() : Promise.reject(r.status))
      .then(data => {
        const files: WorkspaceFile[] = data.files ?? [];
        setFileTree(files);
        setExpandedDirPaths(prev => {
          const valid = collectDirectoryPaths(files);
          const next = new Set<string>();
          for (const p of prev) {
            if (valid.has(p)) next.add(p);
          }
          return next;
        });
      })
      .catch(err => console.warn('Failed to load file tree:', err))
      .finally(() => {
        if (showLoading) setFileTreeLoading(false);
      });
  }, [workspaceId, fileTree.length]);

  useIssuePreparation({ onFileTreeRefresh: refreshFileTree });

  useEffect(() => {
    didSeedRootDirs.current = false;
    setExpandedDirPaths(new Set());
    setFileTree([]);
  }, [workspaceId]);

  useEffect(() => {
    if (!workspaceId) return;
    refreshFileTree({ showLoading: false });
  }, [workspaceId, filesRefreshTrigger, refreshFileTree]);

  /** Expand top-level directories once per workspace when the tree first loads. */
  useEffect(() => {
    if (fileTree.length === 0 || didSeedRootDirs.current) return;
    didSeedRootDirs.current = true;
    setExpandedDirPaths(prev => {
      const next = new Set(prev);
      for (const f of fileTree) {
        if (f.type === 'directory') next.add(f.path);
      }
      return next;
    });
  }, [fileTree]);

  const toggleDir = useCallback((path: string) => {
    setExpandedDirPaths(prev => {
      const next = new Set(prev);
      if (next.has(path)) next.delete(path);
      else next.add(path);
      return next;
    });
  }, []);

  /**
   * When Files tab is visible: refresh immediately, then every 10s. Pause while panel is collapsed
   * (desktop narrow strip) so we do not poll when the tree is not shown.
   */
  useEffect(() => {
    if (activePanelTab !== 'files' || !workspaceId) return;
    if (collapsed) return;
    refreshFileTree();
    const timer = window.setInterval(refreshFileTree, 10_000);
    return () => clearInterval(timer);
  }, [activePanelTab, workspaceId, collapsed, refreshFileTree]);

  const handleSourceClick = (sourceId: string) => {
    setSelectedSourceId(sourceId);
  };

  const handleFileClick = (path: string) => {
    // Look up sizeBytes from the file tree so FileViewer can skip loading large files
    const findSizeBytes = (nodes: WorkspaceFile[]): number | undefined => {
      for (const n of nodes) {
        if (n.type === 'file' && n.path === path) return n.sizeBytes;
        if (n.children) { const r = findSizeBytes(n.children); if (r !== undefined) return r; }
      }
      return undefined;
    };
    setOpenFilePath(path, findSizeBytes(fileTree));
  };

  const handleInventoryAction = (action?: InventoryAction) => {
    if (!action) return;
    if (action.kind === 'file' && action.path) {
      handleFileClick(action.path);
      return;
    }
    if (action.kind === 'source' && action.sourceId) {
      handleSourceClick(action.sourceId);
      return;
    }
    if (action.kind === 'skill_hub') {
      onOpenSkillHub?.();
    }
  };

  const inventory = resolveSourcesInventory({ sources, enabledSkills, files: fileTree });
  const fileCount = countFiles(fileTree);

  const resolveInventoryTone = (status: InventoryItem['status']) => {
    const palette: Record<string, { dot: string; background: string; border: string; text: string }> = {
      ready: { dot: '#16a34a', background: '#ffffff', border: '#dde3ea', text: '#1f2328' },
      partial: { dot: '#d97706', background: '#ffffff', border: '#dde3ea', text: '#1f2328' },
      loading: { dot: '#2563eb', background: '#f8fbff', border: '#d6e4ff', text: '#1f2328' },
      missing: { dot: '#c0c7d1', background: '#fafbfc', border: '#e6e9ee', text: '#7b8794' },
      error: { dot: '#dc2626', background: '#fffafa', border: '#f1d5d5', text: '#1f2328' },
      available: { dot: '#16a34a', background: '#ffffff', border: '#dde3ea', text: '#1f2328' },
      blocked: { dot: '#94a3b8', background: '#fafbfc', border: '#e6e9ee', text: '#7b8794' },
    };
    return palette[status];
  };

  const renderDataSourceChip = (item: InventoryItem) => {
    const tone = resolveInventoryTone(item.status);
    return (
    <Tooltip
      key={item.id}
      label={item.capability || item.description}
      multiline
      w={280}
      withArrow
      position="right"
      styles={{ tooltip: { fontSize: '12px', lineHeight: 1.45 } }}
    >
      <Box
        onClick={item.action ? () => handleInventoryAction(item.action) : undefined}
        title={item.details || item.description}
        style={{
          padding: '8px 10px',
          borderRadius: '10px',
          backgroundColor: tone.background,
          border: `1px solid ${tone.border}`,
          color: tone.text,
          minHeight: '40px',
          display: 'flex',
          alignItems: 'center',
          gap: '8px',
          cursor: item.action ? 'pointer' : 'default',
          transition: 'border-color 0.12s ease, background-color 0.12s ease',
        }}
      >
        <Box
          style={{
            width: '6px',
            height: '6px',
            borderRadius: '999px',
            backgroundColor: tone.dot,
            flexShrink: 0,
          }}
        />
        <Text
          size="xs"
          fw={600}
          style={{
            color: 'inherit',
            lineHeight: 1.2,
            minWidth: 0,
          }}
        >
          {item.title}
        </Text>
      </Box>
    </Tooltip>
    );
  };

  const inventoryItems = inventory.groups.flatMap(group => group.items);

  return (
    <Stack
      gap={0}
      style={{
        height: '100%',
        backgroundColor: '#f4f5f7',
        borderRadius: 'inherit',
        width: '100%',
        overflow: 'hidden',
        position: 'relative',
      }}
    >
      {/* Tabs header */}
      {!collapsed && (
        <Box
          style={{
            backgroundColor: '#f8f9fb',
            borderBottom: '1px solid #e1e5ea',
            flexShrink: 0,
          }}
        >
          <Group
            justify="flex-start"
            align="center"
            wrap="nowrap"
            style={{
              padding: '8px 10px',
              gap: 8,
            }}
          >
            <Group
              gap={4}
              wrap="nowrap"
              style={{
                minWidth: 0,
                justifyContent: 'flex-start',
              }}
            >
              {visibleTabs.map(tab => (
                <Box
                  key={tab}
                  px={10}
                  py={6}
                  onClick={() => setActiveTab(tab)}
                  style={{
                    cursor: 'pointer',
                    borderRadius: '999px',
                    border: activePanelTab === tab ? '1px solid #c7ddfb' : '1px solid transparent',
                    backgroundColor: activePanelTab === tab ? '#eef6ff' : 'transparent',
                    color: activePanelTab === tab ? '#1f2328' : '#5f6a7a',
                    fontWeight: activePanelTab === tab ? 600 : 500,
                    fontSize: '12px',
                    transition: 'all 0.12s ease',
                    display: 'flex',
                    alignItems: 'center',
                    gap: 4,
                    whiteSpace: 'nowrap',
                    flexShrink: 0,
                  }}
                >
                  {tab === 'overview' ? t('sources.tab.overview') : tab === 'integrated_data' ? t('sources.tab.integratedData') : t('sources.tab.files')}
                </Box>
              ))}
            </Group>
            {isOwner && hasPreparedSources && (
              <Tooltip label={t('sources.addIssueSource')}>
                <ActionIcon
                  variant="subtle"
                  color="blue"
                  size="sm"
                  onClick={() => setShowAddModal(true)}
                  aria-label={t('sources.addIssueSource')}
                  style={{
                    marginLeft: 'auto',
                    border: '1px solid #c7ddfb',
                    backgroundColor: '#eef6ff',
                    color: '#0f62c9',
                    flexShrink: 0,
                  }}
                >
                  <span style={{ fontSize: '14px', lineHeight: 1, fontWeight: 700 }}>+</span>
                </ActionIcon>
              </Tooltip>
            )}
          </Group>
        </Box>
      )}

      {/* Tab content */}
      <Box
        style={{
          flex: 1,
          overflowY: 'auto',
          padding: collapsed ? 0 : activePanelTab === 'files' ? '0' : '12px',
        }}
      >
        {collapsed ? (
          <Box
            style={{
              height: '100%',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              color: '#98a2b3',
              fontSize: '11px',
              fontWeight: 700,
              letterSpacing: '0.08em',
              textTransform: 'uppercase',
              writingMode: 'vertical-rl',
              transform: 'rotate(180deg)',
            }}
          >
            Sources
          </Box>
        ) : activePanelTab === 'overview' ? (
          <Stack gap={12} style={{ minHeight: '100%' }}>
            {isOwner && (
              <Button
                variant="subtle"
                color="blue"
                size="sm"
                fullWidth
                onClick={() => setShowAddModal(true)}
                leftSection={<span style={{ fontSize: '14px', lineHeight: 1, fontWeight: 700 }}>+</span>}
                style={{
                  justifyContent: 'flex-start',
                  height: '36px',
                  borderRadius: '4px',
                  backgroundColor: '#eef6ff',
                  border: '1px solid #c7ddfb',
                  color: '#0f62c9',
                }}
              >
                {t('sources.addIssueSource')}
              </Button>
            )}

            <Box
              style={{
                padding: '12px',
                borderRadius: '8px',
                backgroundColor: '#ffffff',
                border: '1px solid #dde3ea',
              }}
            >
              <Stack gap={8}>
                <Text size="sm" fw={700} style={{ color: '#1f2328' }}>{t('sources.overviewTitle')}</Text>
                <Text size="xs" style={{ color: '#667085', lineHeight: 1.5 }}>
                  {t('sources.overviewIntro')}
                </Text>
              </Stack>
            </Box>

            <Box
              style={{
                padding: '12px',
                borderRadius: '8px',
                backgroundColor: '#ffffff',
                border: '1px solid #dde3ea',
              }}
            >
              <Stack gap={8}>
                <Group justify="space-between" align="center" wrap="nowrap">
                  <Text size="sm" fw={700} style={{ color: '#1f2328' }}>{t('sources.issueSources')}</Text>
                  <Text size="xs" style={{ color: '#667085' }}>{preparedSources.length}</Text>
                </Group>
                {preparedSources.length > 0 ? (
                  <Stack gap={6}>
                    {preparedSources.map(source => (
                      <SourceCard
                        key={source.id}
                        source={source}
                        isSelected={false}
                        onClick={() => handleSourceClick(source.id)}
                      />
                    ))}
                  </Stack>
                ) : (
                  <Text size="xs" style={{ color: '#667085', lineHeight: 1.5 }}>
                    {t('sources.noIssueSources')}
                  </Text>
                )}
              </Stack>
            </Box>

            <Box
              style={{
                marginTop: 'auto',
                paddingTop: 12,
                borderTop: '1px solid #e1e5ea',
              }}
            >
              <Group justify="space-between" align="center" wrap="nowrap">
                <Group gap={8} align="center">
                  <Text size="xs" fw={700} style={{ color: '#667085', letterSpacing: '0.04em', textTransform: 'uppercase' }}>
                    {t('sources.skills')}
                  </Text>
                  <Box
                    px={7}
                    py={3}
                    style={{
                      borderRadius: '999px',
                      backgroundColor: '#ffffff',
                      border: '1px solid #d8dee6',
                      color: '#475467',
                      fontSize: '10px',
                      lineHeight: 1,
                      fontWeight: 700,
                    }}
                  >
                    {inventory.activeSkills.count}
                  </Box>
                </Group>
                <Group gap={8} align="center">
                  <Button
                    variant="subtle"
                    color="blue"
                    size="xs"
                    onClick={() => handleInventoryAction(inventory.activeSkills.action)}
                    disabled={!onOpenSkillHub}
                    style={{
                      height: '26px',
                      minHeight: '26px',
                      paddingLeft: '8px',
                      paddingRight: '8px',
                      borderRadius: '999px',
                      backgroundColor: '#ffffff',
                      border: '1px solid #d8dee6',
                      color: '#667085',
                    }}
                  >
                    {inventory.activeSkills.action.label}
                  </Button>
                </Group>
              </Group>
            </Box>
          </Stack>
        ) : activePanelTab === 'integrated_data' ? (
          <Stack gap={12}>
            <Box
              style={{
                padding: '10px 12px',
                borderRadius: '8px',
                backgroundColor: '#ffffff',
                border: '1px solid #dde3ea',
              }}
            >
              <Stack gap={8}>
                <Text size="sm" fw={700} style={{ color: '#1f2328' }}>{t('sources.integratedDataTitle')}</Text>
                <Text size="xs" style={{ color: '#667085', lineHeight: 1.5 }}>
                  {t('sources.integratedDataIntro')}
                </Text>
                <Text size="xs" fw={700} style={{ color: '#475467', letterSpacing: '0.02em' }}>{t('sources.tipsLabel')}</Text>
                <Stack gap={6}>
                  {[
                    t('sources.tip1'),
                    t('sources.tip2'),
                  ].map((tip) => (
                    <Box
                      key={tip}
                      style={{
                        padding: '8px 10px',
                        borderRadius: '10px',
                        background: 'linear-gradient(180deg, #f8fbff 0%, #f3f7fd 100%)',
                        border: '1px solid #d8e6fb',
                      }}
                    >
                      <Group gap={8} align="flex-start" wrap="nowrap">
                        <Box
                          style={{
                            width: '18px',
                            height: '18px',
                            borderRadius: '999px',
                            backgroundColor: '#e8f1ff',
                            border: '1px solid #c7ddfb',
                            color: '#0f62c9',
                            fontSize: '10px',
                            fontWeight: 700,
                            lineHeight: '16px',
                            textAlign: 'center',
                            flexShrink: 0,
                          }}
                        >
                          ?
                        </Box>
                        <Text size="xs" style={{ color: '#516071', lineHeight: 1.4 }}>
                          {tip}
                        </Text>
                      </Group>
                    </Box>
                  ))}
                </Stack>
              </Stack>
            </Box>
            <Stack gap={10}>
              <Text size="sm" fw={700} style={{ color: '#1f2328' }}>{t('sources.availableSignals')}</Text>
              <Box
                style={{
                  display: 'grid',
                  gridTemplateColumns: 'repeat(auto-fit, minmax(92px, 1fr))',
                  gap: '8px',
                }}
              >
                {inventoryItems.map(renderDataSourceChip)}
              </Box>
            </Stack>
          </Stack>
        ) : (
          /* Files tab - VS Code style file tree */
          <Stack gap={0} style={{ minHeight: '100%' }}>
            <Group
              justify="space-between"
              align="center"
              wrap="nowrap"
              style={{
                padding: '8px 10px',
                borderBottom: '1px solid #e1e5ea',
                backgroundColor: '#f8f9fb',
                flexShrink: 0,
              }}
            >
              <Group gap={6} align="center" wrap="nowrap" style={{ minWidth: 0 }}>
                <Text size="xs" fw={700} style={{ color: '#475467', letterSpacing: '0.04em', textTransform: 'uppercase' }}>
                  {t('sources.tab.files')}
                </Text>
                <Text size="xs" style={{ color: '#98a2b3' }}>
                  {fileCount}
                </Text>
              </Group>
              <Tooltip label={t('sources.refreshFileTree')}>
                <ActionIcon
                  variant="subtle"
                  color="gray"
                  size="sm"
                  onClick={triggerFilesRefresh}
                  aria-label={t('sources.refreshFileTree')}
                  style={{ flexShrink: 0 }}
                >
                  <span style={{ fontSize: '12px', lineHeight: 1 }}>↻</span>
                </ActionIcon>
              </Tooltip>
            </Group>
            <Box style={{ padding: '4px 0', flex: 1 }}>
              {fileTreeLoading ? (
                <Box p="md"><Text size="xs" c="carbon.5">{t('sources.loadingFiles')}</Text></Box>
              ) : fileTree.length === 0 ? (
                <Box p="md"><Text size="xs" c="carbon.5">{t('sources.noFiles')}</Text></Box>
              ) : (
                <FileTree
                  files={fileTree}
                  selectedPath={openFilePath}
                  onFileClick={handleFileClick}
                  expandedDirPaths={expandedDirPaths}
                  onToggleDir={toggleDir}
                />
              )}
            </Box>
          </Stack>
        )}
      </Box>

      {onToggleCollapsed && (
        <Tooltip label={collapsed ? 'Expand Sources' : 'Collapse Sources'} position="right" withArrow>
          <ActionIcon
            variant="subtle"
            color="gray"
            size={collapsed ? 'md' : 'sm'}
            onClick={onToggleCollapsed}
            aria-label={collapsed ? 'Expand Sources' : 'Collapse Sources'}
            style={{
              position: 'absolute',
              top: '50%',
              right: collapsed ? 8 : -1,
              transform: 'translateY(-50%)',
              width: collapsed ? 28 : 14,
              height: 48,
              border: '1px solid #d8dee6',
              borderRightColor: collapsed ? '#d8dee6' : '#cfd6df',
              borderRadius: collapsed ? '999px' : '999px 0 0 999px',
              backgroundColor: collapsed ? '#ffffff' : 'rgba(255,255,255,0.86)',
              color: '#667085',
              cursor: 'pointer',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              padding: 0,
              boxShadow: collapsed ? '0 1px 2px rgba(16,24,40,0.06)' : '0 1px 2px rgba(16,24,40,0.04)',
              opacity: collapsed ? 0.9 : 0.68,
              transition: 'opacity 0.12s ease, background-color 0.12s ease, border-color 0.12s ease',
              zIndex: 2,
            }}
            onMouseEnter={(e: React.MouseEvent<HTMLButtonElement>) => {
              e.currentTarget.style.opacity = '1';
              e.currentTarget.style.backgroundColor = '#ffffff';
              e.currentTarget.style.borderColor = '#c5ccd6';
            }}
            onMouseLeave={(e: React.MouseEvent<HTMLButtonElement>) => {
              e.currentTarget.style.opacity = collapsed ? '0.9' : '0.68';
              e.currentTarget.style.backgroundColor = collapsed ? '#ffffff' : 'rgba(255,255,255,0.86)';
              e.currentTarget.style.borderColor = '#d8dee6';
            }}
          >
            <span style={{ fontSize: '13px', lineHeight: 1 }}>{collapsed ? '›' : '‹'}</span>
          </ActionIcon>
        </Tooltip>
      )}

      {isOwner && (
        <AddSourceModal
          opened={showAddModal}
          onClose={() => setShowAddModal(false)}
        />
      )}
    </Stack>
  );
}
