/**
 * TaskList — 任务列表
 *
 * 显示当前会话的任务，支持新增、完成切换、删除、展开查看描述。
 */

import { useState, useEffect, useCallback, useRef } from 'react';
import {
  Box, Typography, Stack, List, ListItem, ListItemIcon,
  Checkbox, Chip, IconButton, TextField, Button, Select, MenuItem, Collapse,
} from '@mui/material';
import { ListChecks, Plus, Trash2, ChevronRight, Circle } from 'lucide-react';
import { useAgentStore } from '@renderer/stores/agent-store';
import { formatTime } from '@renderer/lib/formatters';

// ===== 类型 =====

type TaskStatus = MetonaTask['status'];
type TaskPriority = MetonaTask['priority'];

// ===== 常量 =====

const STATUS_LABELS: Record<TaskStatus, string> = {
  pending: '待处理',
  in_progress: '进行中',
  completed: '已完成',
  blocked: '阻塞',
  cancelled: '已取消',
};

const STATUS_COLORS: Record<TaskStatus, string> = {
  pending: '#f59e0b',
  in_progress: '#a855f7',
  completed: '#22c55e',
  blocked: '#ef4444',
  cancelled: '#64748b',
};

const PRIORITY_LABELS: Record<TaskPriority, string> = {
  low: '低',
  medium: '中',
  high: '高',
  critical: '紧急',
};

const PRIORITY_COLORS: Record<TaskPriority, string> = {
  low: '#64748b',
  medium: '#3b82f6',
  high: '#f97316',
  critical: '#ef4444',
};

const PRIORITY_OPTIONS: TaskPriority[] = ['low', 'medium', 'high', 'critical'];

// ===== 主组件 =====

export function TaskList(): React.JSX.Element {
  const sessionId = useAgentStore((s) => s.currentSessionId);
  const [tasks, setTasks] = useState<MetonaTask[]>([]);
  const [error, setError] = useState<string | null>(null);
  const [showAddForm, setShowAddForm] = useState(false);
  const [newTitle, setNewTitle] = useState('');
  const [newPriority, setNewPriority] = useState<TaskPriority>('medium');
  const [expandedId, setExpandedId] = useState<string | null>(null);
  const [creating, setCreating] = useState(false);
  // M-51 修复: 竞态保护 ref，防止快速切换会话时旧请求覆盖新数据
  const loadReqIdRef = useRef(0);

  const loadTasks = useCallback(async (sid?: string) => {
    if (!window.metona?.tasks?.list) return;
    const reqId = ++loadReqIdRef.current;
    try {
      setError(null);
      const res = await window.metona.tasks.list(sid);
      // 竞态保护：若已被新请求取代或组件已卸载，放弃本次结果
      if (loadReqIdRef.current !== reqId) return;
      if (!res.success) {
        setError('加载任务失败');
        return;
      }
      const list = (res.data ?? []).slice().sort((a, b) => {
        if (a.order_idx !== b.order_idx) return a.order_idx - b.order_idx;
        return a.created_at - b.created_at;
      });
      setTasks(list);
    } catch (err) {
      if (loadReqIdRef.current !== reqId) return;
      setError((err as Error).message ?? '加载任务失败');
    }
  }, []);

  useEffect(() => {
    loadTasks(sessionId ?? undefined);
    // cleanup: 使当前请求失效（防止卸载后 setState + 竞态）
    return () => { loadReqIdRef.current++; };
  }, [sessionId, loadTasks]);

  // P2（v0.3.13）: 订阅任务变更事件（Agent 通过 task_manager 工具写入后自动刷新）
  useEffect(() => {
    if (!window.metona?.tasks?.onTaskChanged) return;
    const unsubscribe = window.metona.tasks.onTaskChanged((changedSessionId) => {
      // 只刷新当前会话的任务
      if (changedSessionId === sessionId) {
        loadTasks(sessionId ?? undefined);
      }
    });
    return unsubscribe;
  }, [sessionId, loadTasks]);

  const handleCreate = async () => {
    if (!sessionId) {
      // 用户主动操作失败应用 toast（与项目惯例一致）
      import('@metona-team/metona-toast').then((mod) => mod.default.error('请先选择或创建会话')).catch(() => {});
      return;
    }
    if (!newTitle.trim()) {
      // 表单校验保留 inline error（让用户看到具体哪个字段有问题）
      setError('任务标题不能为空');
      return;
    }
    if (!window.metona?.tasks?.create) return;
    setCreating(true);
    setError(null);
    try {
      const res = await window.metona.tasks.create({
        sessionId,
        title: newTitle.trim(),
        priority: newPriority,
      });
      if (!res.success) {
        import('@metona-team/metona-toast').then((mod) => mod.default.error(res.error ?? '创建任务失败')).catch(() => {});
        return;
      }
      setNewTitle('');
      setNewPriority('medium');
      setShowAddForm(false);
      await loadTasks(sessionId);
    } catch (err) {
      import('@metona-team/metona-toast').then((mod) => mod.default.error((err as Error).message ?? '创建任务失败')).catch(() => {});
    } finally {
      setCreating(false);
    }
  };

  const handleToggleComplete = async (task: MetonaTask) => {
    if (!window.metona?.tasks?.update) return;
    if (!sessionId) return;
    const nextStatus: TaskStatus = task.status === 'completed' ? 'pending' : 'completed';
    try {
      const res = await window.metona.tasks.update(task.id, { status: nextStatus }, sessionId);
      if (!res.success) {
        import('@metona-team/metona-toast').then((mod) => mod.default.error(res.error ?? '更新任务失败')).catch(() => {});
        return;
      }
      await loadTasks(sessionId ?? undefined);
    } catch (err) {
      import('@metona-team/metona-toast').then((mod) => mod.default.error((err as Error).message ?? '更新任务失败')).catch(() => {});
    }
  };

  const handleDelete = async (id: string) => {
    if (!window.metona?.tasks?.delete) return;
    if (!sessionId) return;
    try {
      const res = await window.metona.tasks.delete(id, sessionId);
      if (!res.success) {
        import('@metona-team/metona-toast').then((mod) => mod.default.error(res.error ?? '删除任务失败')).catch(() => {});
        return;
      }
      if (expandedId === id) setExpandedId(null);
      await loadTasks(sessionId ?? undefined);
    } catch (err) {
      import('@metona-team/metona-toast').then((mod) => mod.default.error((err as Error).message ?? '删除任务失败')).catch(() => {});
    }
  };

  const toggleExpand = (id: string) => {
    setExpandedId(expandedId === id ? null : id);
  };

  return (
    <Box sx={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden', minHeight: 0 }}>
      <Stack direction="row" spacing={1} sx={{ mb: 1.5, flexShrink: 0, alignItems: 'center' }}>
        <ListChecks size={14} style={{ color: '#22d3ee' }} />
        <Typography variant="caption" sx={{ fontWeight: 600, textTransform: 'uppercase', letterSpacing: 1, color: 'text.secondary' }}>
          任务列表
        </Typography>
        <Typography variant="caption" sx={{ ml: 'auto', color: 'text.disabled', fontSize: 10 }}>
          {tasks.length} 项
        </Typography>
        <IconButton
          size="small"
          onClick={() => setShowAddForm(!showAddForm)}
          sx={{ p: 0.25, color: 'primary.main', '&:hover': { bgcolor: 'action.hover' } }}
          title="新增任务"
        >
          <Plus size={14} />
        </IconButton>
      </Stack>

      {error && (
        <Typography
          variant="caption"
          sx={{
            mb: 1, px: 1, py: 0.5, fontSize: 10,
            color: 'error.main', bgcolor: 'error.main' + '14',
            borderRadius: 1, flexShrink: 0,
          }}
        >
          {error}
        </Typography>
      )}

      <Collapse in={showAddForm} sx={{ flexShrink: 0 }}>
        <Box sx={{ mb: 1.5, p: 1, borderRadius: 1, bgcolor: 'background.default', border: '1px solid', borderColor: 'divider' }}>
          <TextField
            size="small"
            fullWidth
            value={newTitle}
            onChange={(e) => setNewTitle(e.target.value)}
            onKeyDown={(e) => { if (e.key === 'Enter') handleCreate(); }}
            placeholder="任务标题..."
            sx={{ mb: 1, '& .MuiOutlinedInput-root': { fontSize: 11, height: 30, borderRadius: 1 } }}
          />
          <Stack direction="row" spacing={1} sx={{ alignItems: 'center' }}>
            <Select
              size="small"
              value={newPriority}
              onChange={(e) => setNewPriority(e.target.value as TaskPriority)}
              sx={{ flex: 1, height: 28, fontSize: 11, '& .MuiSelect-select': { py: 0.5, px: 1 } }}
            >
              {PRIORITY_OPTIONS.map((p) => (
                <MenuItem key={p} value={p} sx={{ fontSize: 11, py: 0.5 }}>
                  <Stack direction="row" spacing={1} sx={{ alignItems: 'center' }}>
                    <Circle size={8} style={{ color: PRIORITY_COLORS[p] }} />
                    <Typography variant="caption" sx={{ fontSize: 11 }}>{PRIORITY_LABELS[p]}</Typography>
                  </Stack>
                </MenuItem>
              ))}
            </Select>
            <Button
              variant="contained"
              size="small"
              onClick={handleCreate}
              disabled={creating || !newTitle.trim()}
              sx={{ height: 28, fontSize: 11, minWidth: 60, textTransform: 'none' }}
            >
              {creating ? '...' : '创建'}
            </Button>
            <IconButton
              size="small"
              onClick={() => { setShowAddForm(false); setNewTitle(''); setNewPriority('medium'); }}
              sx={{ p: 0.5, color: 'text.secondary' }}
            >
              <Trash2 size={12} />
            </IconButton>
          </Stack>
        </Box>
      </Collapse>

      <Box sx={{ flex: 1, overflowY: 'auto', minHeight: 0 }}>
        {!sessionId ? (
          <Typography variant="caption" sx={{ textAlign: 'center', py: 4, display: 'block', color: 'text.disabled' }}>
            请先选择会话
          </Typography>
        ) : tasks.length === 0 ? (
          <Typography variant="caption" sx={{ textAlign: 'center', py: 4, display: 'block', color: 'text.disabled' }}>
            暂无任务，点击 + 创建
          </Typography>
        ) : (
          <List disablePadding dense>
            {tasks.map((task) => (
              <TaskItemRow
                key={task.id}
                task={task}
                expanded={expandedId === task.id}
                onToggleComplete={() => handleToggleComplete(task)}
                onToggleExpand={() => toggleExpand(task.id)}
                onDelete={() => handleDelete(task.id)}
              />
            ))}
          </List>
        )}
      </Box>
    </Box>
  );
}

// ===== 子组件 =====

function TaskItemRow({
  task,
  expanded,
  onToggleComplete,
  onToggleExpand,
  onDelete,
}: {
  task: MetonaTask;
  expanded: boolean;
  onToggleComplete: () => void;
  onToggleExpand: () => void;
  onDelete: () => void;
}): React.JSX.Element {
  const isCompleted = task.status === 'completed';
  const statusColor = STATUS_COLORS[task.status];
  const priorityColor = PRIORITY_COLORS[task.priority];

  return (
    <ListItem
      disableGutters
      disablePadding
      sx={{
        display: 'block',
        px: 0.5, py: 0.25,
        borderRadius: 1,
        '&:hover': { bgcolor: 'action.hover' },
        '&:hover .delete-btn': { opacity: 1 },
      }}
    >
      <Stack direction="row" spacing={0.5} sx={{ alignItems: 'flex-start' }}>
        <ListItemIcon sx={{ minWidth: 20, mt: 0.25 }}>
          <Checkbox
            size="small"
            checked={isCompleted}
            onChange={onToggleComplete}
            sx={{ p: 0.25, '& .MuiSvgIcon-root': { fontSize: 14 } }}
          />
        </ListItemIcon>
        <Box sx={{ flex: 1, minWidth: 0 }}>
          <Box
            onClick={onToggleExpand}
            sx={{
              fontSize: 11, lineHeight: 1.3, cursor: 'pointer',
              color: isCompleted ? 'text.disabled' : 'text.primary',
              textDecoration: isCompleted ? 'line-through' : 'none',
              overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
            }}
          >
            {task.title}
          </Box>
          <Stack direction="row" spacing={0.5} sx={{ alignItems: 'center', mt: 0.25, flexWrap: 'wrap' }}>
            <Chip
              label={STATUS_LABELS[task.status]}
              size="small"
              sx={{
                height: 14, fontSize: 9,
                bgcolor: statusColor + '22', color: statusColor,
                '& .MuiChip-label': { px: 0.5 },
              }}
            />
            <Chip
              label={PRIORITY_LABELS[task.priority]}
              size="small"
              sx={{
                height: 14, fontSize: 9,
                bgcolor: priorityColor + '22', color: priorityColor,
                '& .MuiChip-label': { px: 0.5 },
              }}
            />
            <Typography
              variant="caption"
              component="span"
              sx={{ fontSize: 9, color: 'text.disabled', fontFamily: 'monospace' }}
            >
              {formatTime(task.created_at)}
            </Typography>
          </Stack>
        </Box>
        <ChevronRight
          size={12}
          style={{
            color: 'text.disabled',
            transition: 'transform 150ms',
            transform: expanded ? 'rotate(90deg)' : 'rotate(0deg)',
            cursor: 'pointer',
            marginTop: 4,
          }}
          onClick={onToggleExpand}
        />
        <IconButton
          className="delete-btn"
          size="small"
          onClick={onDelete}
          sx={{ opacity: 0, transition: 'opacity 150ms', p: 0.25, mt: 0.25, '&:hover': { color: 'error.main' } }}
        >
          <Trash2 size={11} />
        </IconButton>
      </Stack>
      <Collapse in={expanded} timeout="auto" unmountOnExit>
        <Box sx={{ pl: 3.5, pr: 1, py: 0.5, fontSize: 11, color: 'text.secondary', lineHeight: 1.4, wordBreak: 'break-word' }}>
          {task.description ? task.description : (
            <Typography variant="caption" sx={{ fontSize: 10, color: 'text.disabled', fontStyle: 'italic' }}>
              无描述
            </Typography>
          )}
        </Box>
      </Collapse>
    </ListItem>
  );
}
