/**
 * CheckpointPanel Component
 *
 * 检查点管理面板：显示所有检查点、创建/删除、查看差异、恢复
 */

import { useState, useEffect, useCallback } from 'react';
import {
  X,
  RefreshCw,
  History,
  Plus,
  Trash2,
  ChevronDown,
  ChevronRight,
  FileText,
  Clock,
  AlertTriangle,
  RotateCcw,
  Undo2,
  Eye,
} from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
import { toast } from 'sonner';
import { cn } from '../utils/cn';
import { modalOverlay, modalContent, smoothTransition } from '../utils/animations';
import { Button } from '../primitives/Button';
import { Skeleton } from './Skeleton';
import {
  listCheckpoints,
  getCheckpointStats,
  createCheckpoint,
  deleteCheckpoint,
  getUnrevertStatus,
  unrevert,
  cleanupCheckpoints,
  type CheckpointListItem,
  type CheckpointStats,
  type CheckpointTrigger,
  type UnrevertStatus,
} from '../api/client.js';

interface CheckpointPanelProps {
  onClose: () => void;
  /** 点击查看差异时触发 */
  onViewDiff?: (checkpointId: string) => void;
  /** 点击恢复时触发 */
  onRestore?: (checkpointId: string) => void;
  /** 是否启用响应式布局 */
  responsive?: boolean;
}

// 触发类型图标和颜色
function getTriggerInfo(trigger: CheckpointTrigger) {
  switch (trigger) {
    case 'tool:write_file':
      return { icon: '🟢', label: 'Write File', color: 'text-green-400' };
    case 'tool:edit_file':
      return { icon: '🟡', label: 'Edit File', color: 'text-yellow-400' };
    case 'tool:delete_file':
      return { icon: '🔴', label: 'Delete File', color: 'text-red-400' };
    case 'tool:move_file':
    case 'tool:copy_file':
      return { icon: '🟠', label: 'Move/Copy', color: 'text-orange-400' };
    case 'tool:bash':
      return { icon: '⚡', label: 'Bash', color: 'text-purple-400' };
    case 'manual':
      return { icon: '🔵', label: 'Manual', color: 'text-blue-400' };
    case 'session_start':
      return { icon: '▶️', label: 'Session Start', color: 'text-cyan-400' };
    case 'session_end':
      return { icon: '⏹️', label: 'Session End', color: 'text-cyan-400' };
    case 'pre_rollback':
      return { icon: '🔙', label: 'Pre-Rollback', color: 'text-fg-muted' };
    case 'auto':
    default:
      return { icon: '⚪', label: 'Auto', color: 'text-fg-muted' };
  }
}

// 格式化时间
function formatTime(timestamp: number) {
  const date = new Date(timestamp);
  const now = new Date();
  const diffMs = now.getTime() - date.getTime();
  const diffMins = Math.floor(diffMs / (1000 * 60));
  const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
  const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));

  if (diffMins < 1) return 'Just now';
  if (diffMins < 60) return `${diffMins}m ago`;
  if (diffHours < 24) return `${diffHours}h ago`;
  if (diffDays < 7) return `${diffDays}d ago`;
  return date.toLocaleDateString();
}

// 格式化完整时间
function formatFullTime(timestamp: number) {
  return new Date(timestamp).toLocaleString();
}

// 按日期分组
function groupByDate(checkpoints: CheckpointListItem[]) {
  const groups: { label: string; items: CheckpointListItem[] }[] = [];
  const now = new Date();
  const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000);

  let currentLabel = '';
  let currentItems: CheckpointListItem[] = [];

  for (const cp of checkpoints) {
    const cpDate = new Date(cp.timestamp);
    const cpDay = new Date(cpDate.getFullYear(), cpDate.getMonth(), cpDate.getDate());

    let label: string;
    if (cpDay.getTime() === today.getTime()) {
      label = 'Today';
    } else if (cpDay.getTime() === yesterday.getTime()) {
      label = 'Yesterday';
    } else {
      label = cpDate.toLocaleDateString();
    }

    if (label !== currentLabel) {
      if (currentItems.length > 0) {
        groups.push({ label: currentLabel, items: currentItems });
      }
      currentLabel = label;
      currentItems = [cp];
    } else {
      currentItems.push(cp);
    }
  }

  if (currentItems.length > 0) {
    groups.push({ label: currentLabel, items: currentItems });
  }

  return groups;
}

export function CheckpointPanel({
  onClose,
  onViewDiff,
  onRestore,
  responsive = false,
}: CheckpointPanelProps) {
  // 数据状态
  const [checkpoints, setCheckpoints] = useState<CheckpointListItem[]>([]);
  const [stats, setStats] = useState<CheckpointStats | null>(null);
  const [unrevertStatus, setUnrevertStatus] = useState<UnrevertStatus | null>(null);
  const [expandedGroups, setExpandedGroups] = useState<Set<string>>(new Set(['Today']));

  // UI 状态
  const [loading, setLoading] = useState(true);
  const [refreshing, setRefreshing] = useState(false);
  const [actionLoading, setActionLoading] = useState<string | null>(null);
  const [creating, setCreating] = useState(false);
  const [cleaningUp, setCleaningUp] = useState(false);

  // 加载数据
  const loadData = useCallback(async (showToast = false) => {
    try {
      const [cpResult, statsResult, unrevertResult] = await Promise.all([
        listCheckpoints(),
        getCheckpointStats(),
        getUnrevertStatus(),
      ]);

      if (cpResult.success) {
        setCheckpoints(cpResult.data);
      } else {
        toast.error(cpResult.error || 'Failed to load checkpoints');
      }

      if (statsResult.success) {
        setStats(statsResult.data);
      }

      if (unrevertResult.success) {
        setUnrevertStatus(unrevertResult.data || null);
      }

      if (showToast) {
        toast.success('Checkpoints refreshed');
      }
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Failed to load checkpoints');
    }
  }, []);

  // 初始加载
  useEffect(() => {
    setLoading(true);
    loadData().finally(() => setLoading(false));
  }, [loadData]);

  // 刷新
  const handleRefresh = async () => {
    setRefreshing(true);
    await loadData(true);
    setRefreshing(false);
  };

  // 创建检查点
  const handleCreate = async () => {
    setCreating(true);
    try {
      const result = await createCheckpoint({
        description: 'Manual checkpoint',
      });
      if (result.success) {
        toast.success('Checkpoint created');
        await loadData();
      } else {
        toast.error(result.error || 'Failed to create checkpoint');
      }
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Failed to create checkpoint');
    } finally {
      setCreating(false);
    }
  };

  // 删除检查点
  const handleDelete = async (id: string) => {
    setActionLoading(id);
    try {
      const result = await deleteCheckpoint(id);
      if (result.success) {
        toast.success('Checkpoint deleted');
        await loadData();
      } else {
        toast.error(result.error || 'Failed to delete checkpoint');
      }
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Failed to delete checkpoint');
    } finally {
      setActionLoading(null);
    }
  };

  // 撤销回滚
  const handleUnrevert = async () => {
    setActionLoading('unrevert');
    try {
      const result = await unrevert();
      if (result.success) {
        toast.success(`Unrevert successful: ${result.data?.filesRestored} files restored`);
        await loadData();
      } else {
        toast.error(result.error || 'Failed to unrevert');
      }
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Failed to unrevert');
    } finally {
      setActionLoading(null);
    }
  };

  // 清理检查点
  const handleCleanup = async () => {
    setCleaningUp(true);
    try {
      const result = await cleanupCheckpoints();
      if (result.success) {
        toast.success(`Cleaned up ${result.data?.deleted || 0} checkpoints`);
        await loadData();
      } else {
        toast.error(result.error || 'Failed to cleanup');
      }
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Failed to cleanup');
    } finally {
      setCleaningUp(false);
    }
  };

  // 切换分组展开
  const toggleGroup = (label: string) => {
    const newExpanded = new Set(expandedGroups);
    if (newExpanded.has(label)) {
      newExpanded.delete(label);
    } else {
      newExpanded.add(label);
    }
    setExpandedGroups(newExpanded);
  };

  // 分组数据
  const groups = groupByDate(checkpoints);

  // Loading 骨架屏
  const LoadingSkeleton = () => (
    <div className="space-y-3 p-4">
      {[1, 2, 3, 4].map((i) => (
        <div key={i} className="flex items-center gap-3 p-3 bg-surface-base/50 rounded-lg">
          <Skeleton className="h-4 w-4 rounded" />
          <div className="flex-1 space-y-2">
            <Skeleton className="h-4 w-48" />
            <Skeleton className="h-3 w-32" />
          </div>
          <Skeleton className="h-8 w-16" />
        </div>
      ))}
    </div>
  );

  return (
    <AnimatePresence>
      <motion.div
        variants={modalOverlay}
        initial="initial"
        animate="animate"
        exit="exit"
        transition={{ duration: 0.2 }}
        className={cn(
          'fixed inset-0 bg-black/50 flex z-50',
          responsive ? 'items-end md:items-center justify-center' : 'items-center justify-center'
        )}
        onClick={onClose}
      >
        <motion.div
          variants={modalContent}
          initial="initial"
          animate="animate"
          exit="exit"
          transition={smoothTransition}
          onClick={(e) => e.stopPropagation()}
          className={cn(
            'bg-surface-subtle max-h-[90vh] overflow-hidden flex flex-col',
            responsive
              ? 'w-full md:w-full md:max-w-2xl md:mx-4 rounded-t-2xl md:rounded-lg'
              : 'rounded-lg w-full max-w-2xl mx-4'
          )}
        >
          {/* Header */}
          <div
            className={cn(
              'flex items-center justify-between border-b border-line',
              responsive ? 'px-4 md:px-6 py-4' : 'px-6 py-4'
            )}
          >
            {responsive && (
              <div className="absolute top-2 left-1/2 -translate-x-1/2 w-10 h-1 bg-surface-emphasis rounded-full md:hidden" />
            )}
            <div className={cn(responsive && 'mt-2 md:mt-0')}>
              <h2 className="text-lg font-semibold flex items-center gap-2">
                <History size={20} className="text-primary-400" />
                Checkpoints
              </h2>
              <p className="text-xs text-fg-subtle">
                {stats ? `${stats.count} checkpoints` : 'Loading...'}
                {stats?.oldestTimestamp && (
                  <> · Oldest: {formatTime(stats.oldestTimestamp)}</>
                )}
              </p>
            </div>
            <div className="flex items-center gap-2">
              <Button
                variant="ghost"
                size="sm"
                onClick={handleCreate}
                disabled={creating}
                title="Create checkpoint"
                className={cn('text-green-400 hover:text-green-300', responsive && 'min-h-[44px]')}
              >
                {creating ? (
                  <div className="animate-spin rounded-full h-4 w-4 border-t-2 border-b-2 border-green-500" />
                ) : (
                  <>
                    <Plus size={16} className="mr-1" />
                    Create
                  </>
                )}
              </Button>
              <Button
                variant="ghost"
                size="icon"
                onClick={handleRefresh}
                disabled={refreshing}
                title="Refresh"
                className={cn(responsive && 'min-w-[44px] min-h-[44px]')}
              >
                <RefreshCw size={18} className={cn(refreshing && 'animate-spin')} />
              </Button>
              <Button
                variant="ghost"
                size="icon"
                onClick={onClose}
                className={cn(responsive && 'min-w-[44px] min-h-[44px]')}
              >
                <X size={20} />
              </Button>
            </div>
          </div>

          {/* Unrevert Banner */}
          {unrevertStatus?.canUnrevert && unrevertStatus.lastRollback && (
            <div className="mx-4 mt-4 p-3 bg-yellow-500/10 border border-yellow-500/30 rounded-lg">
              <div className="flex items-center justify-between">
                <div className="flex items-center gap-2 text-yellow-400">
                  <AlertTriangle size={16} />
                  <span className="text-sm">
                    Last rollback affected {unrevertStatus.lastRollback.restoredFiles.length} files
                  </span>
                </div>
                <Button
                  variant="ghost"
                  size="sm"
                  onClick={handleUnrevert}
                  disabled={actionLoading === 'unrevert'}
                  className="text-yellow-400 hover:text-yellow-300"
                >
                  {actionLoading === 'unrevert' ? (
                    <div className="animate-spin rounded-full h-4 w-4 border-t-2 border-b-2 border-yellow-500" />
                  ) : (
                    <>
                      <Undo2 size={14} className="mr-1" />
                      Unrevert
                    </>
                  )}
                </Button>
              </div>
            </div>
          )}

          {/* Checkpoint List */}
          <div className="flex-1 overflow-y-auto">
            {loading ? (
              <LoadingSkeleton />
            ) : checkpoints.length === 0 ? (
              <div className="flex flex-col items-center justify-center py-12 text-fg-subtle">
                <History size={48} className="mb-4 opacity-50" />
                <p className="text-center">No checkpoints yet</p>
                <p className="text-xs text-fg-subtle mt-2 text-center max-w-xs">
                  Checkpoints are created automatically when files are modified
                </p>
                <Button
                  variant="outline"
                  size="sm"
                  onClick={handleCreate}
                  className="mt-4"
                  disabled={creating}
                >
                  <Plus size={14} className="mr-1" />
                  Create First Checkpoint
                </Button>
              </div>
            ) : (
              <motion.div
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                className={cn('space-y-2', responsive ? 'p-4' : 'p-4')}
              >
                {groups.map((group) => {
                  const isExpanded = expandedGroups.has(group.label);

                  return (
                    <div key={group.label} className="space-y-1">
                      {/* Group Header */}
                      <button
                        className="flex items-center gap-2 text-sm text-fg-muted hover:text-fg-secondary transition-colors w-full"
                        onClick={() => toggleGroup(group.label)}
                      >
                        {isExpanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}
                        <span className="font-medium">{group.label}</span>
                        <span className="text-xs text-fg-subtle">({group.items.length})</span>
                      </button>

                      {/* Group Items */}
                      <AnimatePresence>
                        {isExpanded && (
                          <motion.div
                            initial={{ height: 0, opacity: 0 }}
                            animate={{ height: 'auto', opacity: 1 }}
                            exit={{ height: 0, opacity: 0 }}
                            transition={{ duration: 0.2 }}
                            className="space-y-1 overflow-hidden"
                          >
                            {group.items.map((cp) => {
                              const triggerInfo = getTriggerInfo(cp.trigger);
                              const isLoading = actionLoading === cp.id;

                              return (
                                <motion.div
                                  key={cp.id}
                                  initial={{ opacity: 0, x: -10 }}
                                  animate={{ opacity: 1, x: 0 }}
                                  className="bg-surface-base/50 rounded-lg p-3 hover:bg-surface-base/80 transition-colors"
                                >
                                  <div className="flex items-start gap-3">
                                    {/* Trigger Icon */}
                                    <span className="text-lg" title={triggerInfo.label}>
                                      {triggerInfo.icon}
                                    </span>

                                    {/* Info */}
                                    <div className="flex-1 min-w-0">
                                      <div className="flex items-center gap-2">
                                        <span className={cn('text-sm font-medium', triggerInfo.color)}>
                                          {triggerInfo.label}
                                        </span>
                                        <span className="text-xs text-fg-subtle">
                                          {formatTime(cp.timestamp)}
                                        </span>
                                      </div>
                                      {cp.description && (
                                        <p className="text-xs text-fg-muted mt-0.5 truncate">
                                          {cp.description}
                                        </p>
                                      )}
                                      <div className="flex items-center gap-3 mt-1 text-xs text-fg-subtle">
                                        <span className="flex items-center gap-1">
                                          <FileText size={10} />
                                          {cp.filesChanged} files
                                        </span>
                                        <span className="flex items-center gap-1">
                                          <Clock size={10} />
                                          {formatFullTime(cp.timestamp)}
                                        </span>
                                      </div>
                                    </div>

                                    {/* Actions */}
                                    <div className="flex items-center gap-1">
                                      {isLoading ? (
                                        <div className="animate-spin rounded-full h-5 w-5 border-t-2 border-b-2 border-primary-500" />
                                      ) : (
                                        <>
                                          {onViewDiff && (
                                            <Button
                                              variant="ghost"
                                              size="icon"
                                              onClick={() => onViewDiff(cp.id)}
                                              title="View diff"
                                              className="text-blue-400 hover:text-blue-300"
                                            >
                                              <Eye size={14} />
                                            </Button>
                                          )}
                                          {onRestore && (
                                            <Button
                                              variant="ghost"
                                              size="icon"
                                              onClick={() => onRestore(cp.id)}
                                              title="Restore"
                                              className="text-green-400 hover:text-green-300"
                                            >
                                              <RotateCcw size={14} />
                                            </Button>
                                          )}
                                          <Button
                                            variant="ghost"
                                            size="icon"
                                            onClick={() => handleDelete(cp.id)}
                                            title="Delete"
                                            className="text-red-400 hover:text-red-300"
                                          >
                                            <Trash2 size={14} />
                                          </Button>
                                        </>
                                      )}
                                    </div>
                                  </div>
                                </motion.div>
                              );
                            })}
                          </motion.div>
                        )}
                      </AnimatePresence>
                    </div>
                  );
                })}
              </motion.div>
            )}
          </div>

          {/* Footer */}
          <div
            className={cn(
              'flex items-center justify-between border-t border-line',
              responsive ? 'px-4 py-3 safe-area-pb' : 'px-6 py-3'
            )}
          >
            <span className="text-xs text-fg-subtle">
              Auto-cleanup enabled (7 days / 100 max)
            </span>
            <Button
              variant="ghost"
              size="sm"
              onClick={handleCleanup}
              disabled={cleaningUp}
              className="text-fg-muted hover:text-fg-secondary"
            >
              {cleaningUp ? (
                <div className="animate-spin rounded-full h-3 w-3 border-t-2 border-b-2 border-fg-subtle mr-1" />
              ) : (
                <Trash2 size={12} className="mr-1" />
              )}
              Cleanup Now
            </Button>
          </div>
        </motion.div>
      </motion.div>
    </AnimatePresence>
  );
}
