import React, { useState, useEffect, useMemo, useRef } from 'react';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import Paper from '@mui/material/Paper';
import PsychologyIcon from '@mui/icons-material/Psychology';
import SmartToyOutlinedIcon from '@mui/icons-material/SmartToyOutlined';
import QuestionAnswerOutlinedIcon from '@mui/icons-material/QuestionAnswerOutlined';
import MapOutlinedIcon from '@mui/icons-material/MapOutlined';
import CategoryOutlinedIcon from '@mui/icons-material/CategoryOutlined';
import TuneOutlinedIcon from '@mui/icons-material/TuneOutlined';
import InsertDriveFileOutlinedIcon from '@mui/icons-material/InsertDriveFileOutlined';
import LanguageIcon from '@mui/icons-material/Language';
import BuildOutlinedIcon from '@mui/icons-material/BuildOutlined';
import SvgIcon from '@mui/material/SvgIcon';
import ViewQuiltOutlinedIcon from '@mui/icons-material/ViewQuiltOutlined';
import { useAppSelector, useAppDispatch } from '@/shared/hooks';
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
import { fetchBuiltinTools, fetchTools } from '@/shared/state/toolsSlice';
import { fetchSkills } from '@/shared/state/skillsSlice';

const GoogleIcon: React.FC<{ sx?: object }> = ({ sx }) => (
  <SvgIcon sx={sx} viewBox="0 0 24 24">
    <path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z" fill="#4285F4" />
    <path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853" />
    <path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05" />
    <path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335" />
  </SvgIcon>
);

const RedditIcon: React.FC<{ sx?: object }> = ({ sx }) => (
  <SvgIcon sx={sx} viewBox="0 0 24 24">
    <path d="M14.238 15.348c.085.084.085.221 0 .306-.465.462-1.194.687-2.231.687l-.008-.002-.008.002c-1.036 0-1.766-.225-2.231-.688-.085-.084-.085-.221 0-.305.084-.084.222-.084.307 0 .379.377 1.008.561 1.924.561l.008.002.008-.002c.915 0 1.544-.184 1.924-.561.085-.084.223-.084.307 0zm-3.44-2.418c0-.507-.414-.919-.922-.919-.509 0-.922.412-.922.919 0 .506.414.918.922.918.508 0 .922-.412.922-.918zm4.04-.919c-.509 0-.922.412-.922.919 0 .506.414.918.922.918.508 0 .922-.412.922-.918 0-.507-.414-.919-.922-.919zM12 2C6.478 2 2 6.477 2 12c0 5.522 4.478 10 10 10s10-4.478 10-10c0-5.523-4.478-10-10-10zm5.8 11.333c.02.14.03.283.03.428 0 2.19-2.547 3.964-5.69 3.964-3.142 0-5.69-1.774-5.69-3.964 0-.145.01-.288.03-.428A1.588 1.588 0 0 1 5.6 12c0-.881.716-1.596 1.599-1.596.424 0 .808.17 1.09.443 1.07-.742 2.554-1.22 4.19-1.284l.782-3.674a.11.11 0 0 1 .13-.083l2.603.556a1.132 1.132 0 0 1 2.154.481 1.134 1.134 0 0 1-1.132 1.133 1.132 1.132 0 0 1-1.105-.896l-2.318-.495-.69 3.248c1.6.08 3.046.56 4.094 1.29.283-.278.67-.45 1.099-.45.882 0 1.599.715 1.599 1.596 0 .56-.29 1.05-.726 1.334z" />
  </SvgIcon>
);

const TOOL_GROUP_ICONS: Record<string, React.FC<{ sx?: object }>> = {
  Google: GoogleIcon,
  Reddit: RedditIcon,
  Web: LanguageIcon,
  View: ViewQuiltOutlinedIcon,
};

export function getToolGroupIcon(groupName: string, size: number = 15): React.ReactNode {
  const Icon = TOOL_GROUP_ICONS[groupName];
  if (Icon) return <Icon sx={{ fontSize: size }} />;
  return <BuildOutlinedIcon sx={{ fontSize: size }} />;
}

export interface CommandPickerItem {
  id: string;
  type: 'skill' | 'mode' | 'context';
  category: string;
  name: string;
  description: string;
  command: string;
  icon: React.ReactNode;
  toolNames?: string[];
  iconKey?: string;
}

interface Props {
  trigger: '/' | '@';
  filter: string;
  onSelect: (item: CommandPickerItem) => void;
  onClose: () => void;
  visible: boolean;
}

const MODE_ICON_MAP: Record<string, React.ComponentType<{ sx?: object }>> = {
  smart_toy: SmartToyOutlinedIcon,
  question_answer: QuestionAnswerOutlinedIcon,
  map: MapOutlinedIcon,
  category: CategoryOutlinedIcon,
  tune: TuneOutlinedIcon,
};

function highlightMatch(text: string, query: string, color: string): React.ReactNode {
  if (!query) return text;
  const idx = text.toLowerCase().indexOf(query.toLowerCase());
  if (idx === -1) return text;
  return (
    <>
      {text.slice(0, idx)}
      <span style={{ color, fontWeight: 600 }}>{text.slice(idx, idx + query.length)}</span>
      {text.slice(idx + query.length)}
    </>
  );
}

const CommandPicker: React.FC<Props> = ({ trigger, filter, onSelect, onClose, visible }) => {
  const c = useClaudeTokens();
  const dispatch = useAppDispatch();
  const skills = useAppSelector((s) => s.skills.items);
  const modesMap = useAppSelector((s) => s.modes.items);
  const builtinTools = useAppSelector((s) => s.tools.builtinTools);
  const customTools = useAppSelector((s) => s.tools.items);
  const [selectedIndex, setSelectedIndex] = useState(0);
  const containerRef = useRef<HTMLDivElement>(null);

  const toolsLoaded = useAppSelector((s) => s.tools.loaded);
  const builtinLoaded = useAppSelector((s) => s.tools.builtinLoaded);
  const skillsLoaded = useAppSelector((s) => s.skills.loaded);

  useEffect(() => {
    if (!builtinLoaded) dispatch(fetchBuiltinTools());
    if (!toolsLoaded) dispatch(fetchTools());
    if (!skillsLoaded) dispatch(fetchSkills());
  }, [dispatch, builtinLoaded, toolsLoaded, skillsLoaded]);

  const items: CommandPickerItem[] = useMemo(() => {
    let all: CommandPickerItem[] = [];

    if (trigger === '/') {
      const skillItems: CommandPickerItem[] = Object.values(skills).map((s) => ({
        id: s.id,
        type: 'skill' as const,
        category: 'Skills',
        name: s.name,
        description: s.description || 'Skill',
        command: s.command || s.id,
        icon: <PsychologyIcon sx={{ fontSize: 15 }} />,
      }));

      const modeItems: CommandPickerItem[] = Object.values(modesMap).map((m) => {
        const IconComp = MODE_ICON_MAP[m.icon] || SmartToyOutlinedIcon;
        return {
          id: m.id,
          type: 'mode' as const,
          category: 'Modes',
          name: m.name,
          description: m.description || 'Switch to this mode',
          command: m.name.toLowerCase().replace(/\s+/g, '-'),
          icon: <IconComp sx={{ fontSize: 15 }} />,
        };
      });

      all = [...skillItems, ...modeItems];
    } else {
      const atItems: CommandPickerItem[] = [
        {
          id: 'file',
          type: 'context' as const,
          category: 'Context',
          name: 'File',
          description: 'Attach a file or folder as context',
          command: 'file',
          icon: <InsertDriveFileOutlinedIcon sx={{ fontSize: 15 }} />,
        },
      ];

      const hasWebSearch = builtinTools.some((t) => t.name === 'WebSearch' && t.deferred);
      const hasWebFetch = builtinTools.some((t) => t.name === 'WebFetch' && t.deferred);
      if (hasWebSearch || hasWebFetch) {
        const webTools = [hasWebSearch && 'WebSearch', hasWebFetch && 'WebFetch'].filter(Boolean) as string[];
        atItems.push({
          id: 'web',
          type: 'context' as const,
          category: 'Actions',
          name: 'Web',
          description: 'Search the web and fetch URLs',
          command: 'web',
          icon: <LanguageIcon sx={{ fontSize: 15 }} />,
          toolNames: webTools,
          iconKey: 'Web',
        });
      }

      for (const tool of Object.values(customTools)) {
        if (!tool.mcp_config || Object.keys(tool.mcp_config).length === 0) continue;
        const services = tool.tool_permissions?._services as Record<string, { read: string[]; write: string[] }> | undefined;
        if (!services) continue;
        const perms = tool.tool_permissions as Record<string, any>;
        const serviceGroups = (tool.tool_permissions?._service_groups ?? {}) as Record<string, string[]>;

        const enabledServices: { name: string; tools: string[] }[] = [];
        for (const [serviceName, serviceTools] of Object.entries(services)) {
          const allToolNames = [...(serviceTools.read || []), ...(serviceTools.write || [])];
          const enabled = allToolNames.filter((name) => perms[name] !== 'deny');
          if (enabled.length > 0) enabledServices.push({ name: serviceName, tools: enabled });
        }

        if (enabledServices.length === 0) continue;

        const groupEntries = Object.entries(serviceGroups);
        const emittedServices = new Set<string>();

        for (const [groupName, groupServiceNames] of groupEntries) {
          const groupCmd = groupName.toLowerCase().replace(/\s+/g, '-');
          const groupServices = enabledServices.filter((s) => groupServiceNames.includes(s.name));
          if (groupServices.length === 0) continue;
          groupServices.forEach((s) => emittedServices.add(s.name));

          const groupIcon = getToolGroupIcon(groupName);
          if (groupServices.length >= 2) {
            const allTools = groupServices.flatMap((s) => s.tools);
            atItems.push({
              id: `mcp-${tool.id}-group-${groupName}`,
              type: 'context' as const,
              category: tool.name,
              name: groupName,
              description: `Use all ${groupName} actions`,
              command: groupCmd,
              icon: groupIcon,
              toolNames: allTools,
              iconKey: groupName,
            });
            for (const svc of groupServices) {
              atItems.push({
                id: `mcp-${tool.id}-${svc.name}`,
                type: 'context' as const,
                category: tool.name,
                name: svc.name,
                description: `Use ${svc.name} actions from ${tool.name}`,
                command: `${groupCmd}/${svc.name.toLowerCase().replace(/\s+/g, '-')}`,
                icon: groupIcon,
                toolNames: svc.tools,
                iconKey: groupName,
              });
            }
          } else {
            const svc = groupServices[0];
            atItems.push({
              id: `mcp-${tool.id}-${svc.name}`,
              type: 'context' as const,
              category: tool.name,
              name: svc.name,
              description: `Use ${svc.name} actions from ${tool.name}`,
              command: svc.name.toLowerCase().replace(/\s+/g, '-'),
              icon: groupIcon,
              toolNames: svc.tools,
              iconKey: groupName,
            });
          }
        }

        for (const svc of enabledServices) {
          if (emittedServices.has(svc.name)) continue;
          atItems.push({
            id: `mcp-${tool.id}-${svc.name}`,
            type: 'context' as const,
            category: tool.name,
            name: svc.name,
            description: `Use ${svc.name} actions from ${tool.name}`,
            command: svc.name.toLowerCase().replace(/\s+/g, '-'),
            icon: <BuildOutlinedIcon sx={{ fontSize: 15 }} />,
            toolNames: svc.tools,
          });
        }
      }

      all = atItems;
    }

    if (!filter) return all;
    const lower = filter.toLowerCase();
    return all.filter(
      (item) =>
        item.name.toLowerCase().includes(lower) ||
        item.command.toLowerCase().includes(lower) ||
        item.description.toLowerCase().includes(lower),
    );
  }, [trigger, skills, modesMap, builtinTools, customTools, filter]);

  const flatItems = useMemo(() => {
    const result: { item: CommandPickerItem; isGroupStart: boolean; category: string }[] = [];
    let lastCat = '';
    for (const item of items) {
      result.push({ item, isGroupStart: item.category !== lastCat, category: item.category });
      lastCat = item.category;
    }
    return result;
  }, [items]);

  const getIconColor = (item: CommandPickerItem): string => {
    switch (item.type) {
      case 'skill': return c.status.success;
      case 'mode': {
        const mode = modesMap[item.id];
        return mode?.color || c.accent.primary;
      }
      case 'context': return c.text.tertiary;
      default: return c.text.tertiary;
    }
  };

  useEffect(() => {
    setSelectedIndex(0);
  }, [filter, trigger]);

  useEffect(() => {
    if (!containerRef.current) return;
    const el = containerRef.current.querySelector(`[data-picker-idx="${selectedIndex}"]`);
    if (el) el.scrollIntoView({ block: 'nearest' });
  }, [selectedIndex]);

  useEffect(() => {
    if (!visible) return;
    const handler = (e: KeyboardEvent) => {
      switch (e.key) {
        case 'ArrowDown':
          e.preventDefault();
          setSelectedIndex((p) => (p < items.length - 1 ? p + 1 : p));
          break;
        case 'ArrowUp':
          e.preventDefault();
          setSelectedIndex((p) => (p > 0 ? p - 1 : p));
          break;
        case 'Enter':
        case 'Tab':
          if (items[selectedIndex]) {
            e.preventDefault();
            onSelect(items[selectedIndex]);
          }
          break;
        case 'Escape':
          e.preventDefault();
          onClose();
          break;
      }
    };
    window.addEventListener('keydown', handler);
    return () => window.removeEventListener('keydown', handler);
  }, [visible, items, selectedIndex, onSelect, onClose]);

  if (!visible || items.length === 0) return null;

  return (
    <Paper
      ref={containerRef}
      elevation={0}
      sx={{
        position: 'absolute',
        bottom: '100%',
        left: 0,
        right: 0,
        mb: 0.5,
        bgcolor: c.bg.surface,
        border: `1px solid ${c.border.subtle}`,
        borderRadius: '12px',
        maxHeight: 320,
        overflow: 'auto',
        zIndex: 1000,
        boxShadow: c.shadow.lg,
        animation: 'cmdPickerIn 120ms ease-out',
        '@keyframes cmdPickerIn': {
          from: { opacity: 0, transform: 'translateY(4px)' },
          to: { opacity: 1, transform: 'translateY(0)' },
        },
        '&::-webkit-scrollbar': { width: 4 },
        '&::-webkit-scrollbar-track': { background: 'transparent' },
        '&::-webkit-scrollbar-thumb': {
          background: c.border.medium,
          borderRadius: 2,
          '&:hover': { background: c.border.strong },
        },
        scrollbarWidth: 'thin',
        scrollbarColor: `${c.border.medium} transparent`,
      }}
    >
      <Box sx={{ py: 0.5 }}>
        {flatItems.map(({ item, isGroupStart, category }, idx) => (
          <React.Fragment key={`${item.type}-${item.id}`}>
            {isGroupStart && (
              <Box sx={{ px: 1.5, pt: idx === 0 ? 0.75 : 1.25, pb: 0.375 }}>
                <Typography
                  sx={{
                    color: c.text.ghost,
                    fontSize: '0.625rem',
                    fontWeight: 700,
                    textTransform: 'uppercase',
                    letterSpacing: '0.08em',
                  }}
                >
                  {category}
                </Typography>
              </Box>
            )}
            <Box
              data-picker-idx={idx}
              onClick={() => onSelect(item)}
              onMouseEnter={() => setSelectedIndex(idx)}
              sx={{
                display: 'flex',
                alignItems: 'center',
                gap: 1,
                px: 1.25,
                py: 0.5,
                mx: 0.5,
                borderRadius: '8px',
                cursor: 'pointer',
                bgcolor: idx === selectedIndex ? `${c.accent.primary}0a` : 'transparent',
                '&:hover': { bgcolor: `${c.accent.primary}0a` },
                transition: 'background-color 60ms ease',
              }}
            >
              <Box
                sx={{
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                  width: 24,
                  height: 24,
                  flexShrink: 0,
                  borderRadius: '6px',
                  bgcolor: `${getIconColor(item)}12`,
                  color: getIconColor(item),
                }}
              >
                {item.icon}
              </Box>
              <Typography
                component="span"
                sx={{
                  color: c.text.primary,
                  fontSize: '0.8rem',
                  fontWeight: 500,
                  fontFamily: c.font.mono,
                  whiteSpace: 'nowrap',
                  lineHeight: 1.3,
                }}
              >
                {trigger}{highlightMatch(item.command, filter, c.accent.primary)}
              </Typography>
              <Typography
                component="span"
                sx={{
                  color: c.text.muted,
                  fontSize: '0.72rem',
                  overflow: 'hidden',
                  textOverflow: 'ellipsis',
                  whiteSpace: 'nowrap',
                  flex: 1,
                  ml: 0.5,
                  lineHeight: 1.3,
                }}
              >
                {item.description}
              </Typography>
            </Box>
          </React.Fragment>
        ))}
      </Box>

      <Box
        sx={{
          display: 'flex',
          alignItems: 'center',
          gap: 1.5,
          px: 1.5,
          py: 0.625,
          borderTop: `1px solid ${c.border.subtle}`,
        }}
      >
        {[
          { keys: '↑↓', label: 'navigate' },
          { keys: '↵', label: 'select' },
          { keys: 'esc', label: 'dismiss' },
        ].map(({ keys, label }) => (
          <Box key={label} sx={{ display: 'flex', alignItems: 'center', gap: 0.375 }}>
            <Typography
              sx={{
                fontSize: '0.58rem',
                fontFamily: c.font.mono,
                color: c.text.ghost,
                bgcolor: c.bg.secondary,
                px: 0.5,
                py: 0.125,
                borderRadius: '3px',
                border: `1px solid ${c.border.subtle}`,
                lineHeight: 1.3,
              }}
            >
              {keys}
            </Typography>
            <Typography sx={{ fontSize: '0.58rem', color: c.text.ghost }}>
              {label}
            </Typography>
          </Box>
        ))}
      </Box>
    </Paper>
  );
};

export default CommandPicker;
