/**
 * Identity Change Proposal Component
 *
 * Displays pending personality change proposals with:
 * - Side-by-side diff view
 * - Accept/Reject buttons
 * - Reason explanation
 *
 * Part of ZCLAW L4 Self-Evolution capability.
 */

import { useState, useEffect, useMemo } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import {
  Check,
  X,
  FileText,
  Clock,
  AlertCircle,
  ChevronDown,
  ChevronUp,
  Sparkles,
  History,
} from 'lucide-react';
import {
  intelligenceClient,
  type IdentityChangeProposal as Proposal,
  type IdentitySnapshot,
} from '../lib/intelligence-client';
import { useChatStore } from '../store/chatStore';
import { Button, Badge } from './ui';

// === Diff View Component ===

function DiffView({
  current,
  proposed,
}: {
  current: string;
  proposed: string;
}) {
  const currentLines = useMemo(() => current.split('\n'), [current]);
  const proposedLines = useMemo(() => proposed.split('\n'), [proposed]);

  // Simple line-by-line diff
  const maxLines = Math.max(currentLines.length, proposedLines.length);
  const diffLines: Array<{
    type: 'unchanged' | 'added' | 'removed' | 'modified';
    current?: string;
    proposed?: string;
    lineNum: number;
  }> = [];

  // Build a simple diff - for a production system, use a proper diff algorithm
  // Note: currentSet/proposedSet could be used for advanced diff algorithms
  // const currentSet = new Set(currentLines);
  // const proposedSet = new Set(proposedLines);

  for (let i = 0; i < maxLines; i++) {
    const currLine = currentLines[i];
    const propLine = proposedLines[i];

    if (currLine === propLine) {
      diffLines.push({ type: 'unchanged', current: currLine, proposed: propLine, lineNum: i + 1 });
    } else if (currLine === undefined) {
      diffLines.push({ type: 'added', proposed: propLine, lineNum: i + 1 });
    } else if (propLine === undefined) {
      diffLines.push({ type: 'removed', current: currLine, lineNum: i + 1 });
    } else {
      diffLines.push({ type: 'modified', current: currLine, proposed: propLine, lineNum: i + 1 });
    }
  }

  return (
    <div className="grid grid-cols-2 gap-2 text-xs font-mono">
      {/* Current */}
      <div className="rounded-lg border border-gray-200 dark:border-gray-700 overflow-hidden">
        <div className="bg-red-50 dark:bg-red-900/20 px-2 py-1 text-red-700 dark:text-red-300 font-sans font-medium border-b border-red-100 dark:border-red-800">
          当前版本
        </div>
        <div className="bg-gray-50 dark:bg-gray-800/50 max-h-64 overflow-y-auto">
          {diffLines.map((line, idx) => (
            <div
              key={idx}
              className={`px-2 py-0.5 ${
                line.type === 'removed'
                  ? 'bg-red-100 dark:bg-red-900/30 text-red-700 dark:text-red-300'
                  : line.type === 'modified'
                  ? 'bg-yellow-100 dark:bg-yellow-900/30 text-yellow-700 dark:text-yellow-300'
                  : 'text-gray-600 dark:text-gray-400'
              }`}
            >
              {line.type === 'removed' && <span className="text-red-500 mr-1">-</span>}
              {line.type === 'modified' && <span className="text-yellow-500 mr-1">~</span>}
              {line.current || '\u00A0'}
            </div>
          ))}
        </div>
      </div>

      {/* Proposed */}
      <div className="rounded-lg border border-gray-200 dark:border-gray-700 overflow-hidden">
        <div className="bg-green-50 dark:bg-green-900/20 px-2 py-1 text-green-700 dark:text-green-300 font-sans font-medium border-b border-green-100 dark:border-green-800">
          建议版本
        </div>
        <div className="bg-gray-50 dark:bg-gray-800/50 max-h-64 overflow-y-auto">
          {diffLines.map((line, idx) => (
            <div
              key={idx}
              className={`px-2 py-0.5 ${
                line.type === 'added'
                  ? 'bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300'
                  : line.type === 'modified'
                  ? 'bg-yellow-100 dark:bg-yellow-900/30 text-yellow-700 dark:text-yellow-300'
                  : 'text-gray-600 dark:text-gray-400'
              }`}
            >
              {line.type === 'added' && <span className="text-green-500 mr-1">+</span>}
              {line.type === 'modified' && <span className="text-yellow-500 mr-1">~</span>}
              {line.proposed || '\u00A0'}
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

// === Single Proposal Card ===

function ProposalCard({
  proposal,
  onApprove,
  onReject,
  isProcessing,
}: {
  proposal: Proposal;
  onApprove: () => void;
  onReject: () => void;
  isProcessing: boolean;
}) {
  const [expanded, setExpanded] = useState(true);

  const fileLabel = proposal.file === 'soul' ? 'SOUL.md' : 'Instructions';
  const timeAgo = getTimeAgo(proposal.created_at);

  return (
    <motion.div
      initial={{ opacity: 0, y: 10 }}
      animate={{ opacity: 1, y: 0 }}
      exit={{ opacity: 0, y: -10 }}
      className="rounded-xl border border-orange-200 dark:border-orange-800 bg-orange-50/50 dark:bg-orange-900/10 overflow-hidden"
    >
      {/* Header */}
      <div
        className="px-4 py-3 flex items-center justify-between cursor-pointer hover:bg-orange-100/50 dark:hover:bg-orange-900/20 transition-colors"
        onClick={() => setExpanded(!expanded)}
      >
        <div className="flex items-center gap-3">
          <div className="w-8 h-8 rounded-lg bg-orange-100 dark:bg-orange-900/30 flex items-center justify-center">
            <Sparkles className="w-4 h-4 text-orange-600 dark:text-orange-400" />
          </div>
          <div>
            <div className="flex items-center gap-2">
              <span className="text-sm font-medium text-gray-900 dark:text-gray-100">
                人格变更提案
              </span>
              <Badge variant="warning" className="text-xs">
                {fileLabel}
              </Badge>
            </div>
            <div className="flex items-center gap-2 text-xs text-gray-500 dark:text-gray-400 mt-0.5">
              <Clock className="w-3 h-3" />
              <span>{timeAgo}</span>
            </div>
          </div>
        </div>
        <div className="flex items-center gap-2">
          {expanded ? (
            <ChevronUp className="w-4 h-4 text-gray-400" />
          ) : (
            <ChevronDown className="w-4 h-4 text-gray-400" />
          )}
        </div>
      </div>

      {/* Content */}
      <AnimatePresence>
        {expanded && (
          <motion.div
            initial={{ height: 0, opacity: 0 }}
            animate={{ height: 'auto', opacity: 1 }}
            exit={{ height: 0, opacity: 0 }}
            transition={{ duration: 0.2 }}
            className="overflow-hidden"
          >
            <div className="px-4 pb-4 space-y-4">
              {/* Reason */}
              <div className="rounded-lg bg-white dark:bg-gray-800 p-3 border border-gray-200 dark:border-gray-700">
                <div className="text-xs font-medium text-gray-500 dark:text-gray-400 mb-1">
                  变更原因
                </div>
                <p className="text-sm text-gray-700 dark:text-gray-300">{proposal.reason}</p>
              </div>

              {/* Diff View */}
              <DiffView
                current={proposal.current_content}
                proposed={proposal.suggested_content}
              />

              {/* Actions */}
              <div className="flex items-center justify-end gap-2 pt-2">
                <Button
                  variant="outline"
                  size="sm"
                  onClick={onReject}
                  disabled={isProcessing}
                  className="text-red-600 border-red-200 hover:bg-red-50 dark:border-red-800 dark:hover:bg-red-900/20"
                >
                  <X className="w-4 h-4 mr-1" />
                  拒绝
                </Button>
                <Button
                  variant="primary"
                  size="sm"
                  onClick={onApprove}
                  disabled={isProcessing}
                  className="bg-green-600 hover:bg-green-700"
                >
                  <Check className="w-4 h-4 mr-1" />
                  接受
                </Button>
              </div>
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </motion.div>
  );
}

// === Evolution History Item ===

function HistoryItem({
  snapshot,
  onRestore,
  isRestoring,
}: {
  snapshot: IdentitySnapshot;
  onRestore: () => void;
  isRestoring: boolean;
}) {
  const timeAgo = getTimeAgo(snapshot.timestamp);

  return (
    <div className="flex items-start gap-3 p-3 rounded-lg bg-gray-50 dark:bg-gray-800/50 border border-gray-100 dark:border-gray-700">
      <div className="w-8 h-8 rounded-lg bg-gray-200 dark:bg-gray-700 flex items-center justify-center flex-shrink-0">
        <History className="w-4 h-4 text-gray-500 dark:text-gray-400" />
      </div>
      <div className="flex-1 min-w-0">
        <div className="flex items-center justify-between gap-2">
          <span className="text-xs text-gray-500 dark:text-gray-400">{timeAgo}</span>
          <Button
            variant="ghost"
            size="sm"
            onClick={onRestore}
            disabled={isRestoring}
            className="text-xs text-gray-500 hover:text-orange-600"
          >
            恢复
          </Button>
        </div>
        <p className="text-sm text-gray-700 dark:text-gray-300 mt-1 truncate">
          {snapshot.reason || '自动快照'}
        </p>
      </div>
    </div>
  );
}

// === Main Component ===

export function IdentityChangeProposalPanel() {
  const { currentAgent } = useChatStore();
  const [proposals, setProposals] = useState<Proposal[]>([]);
  const [snapshots, setSnapshots] = useState<IdentitySnapshot[]>([]);
  const [loading, setLoading] = useState(true);
  const [processingId, setProcessingId] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  const agentId = currentAgent?.id;

  // Load data
  useEffect(() => {
    if (!agentId) return;

    const loadData = async () => {
      setLoading(true);
      setError(null);
      try {
        const [pendingProposals, agentSnapshots] = await Promise.all([
          intelligenceClient.identity.getPendingProposals(agentId),
          intelligenceClient.identity.getSnapshots(agentId, 10),
        ]);
        setProposals(pendingProposals);
        setSnapshots(agentSnapshots);
      } catch (err) {
        console.error('[IdentityChangeProposal] Failed to load data:', err);
        setError('加载失败');
      } finally {
        setLoading(false);
      }
    };

    loadData();
  }, [agentId]);

  const handleApprove = async (proposalId: string) => {
    if (!agentId) return;
    setProcessingId(proposalId);
    setError(null);
    try {
      await intelligenceClient.identity.approveProposal(proposalId);
      // Refresh data
      const [pendingProposals, agentSnapshots] = await Promise.all([
        intelligenceClient.identity.getPendingProposals(agentId),
        intelligenceClient.identity.getSnapshots(agentId, 10),
      ]);
      setProposals(pendingProposals);
      setSnapshots(agentSnapshots);
    } catch (err) {
      console.error('[IdentityChangeProposal] Failed to approve:', err);
      setError('审批失败');
    } finally {
      setProcessingId(null);
    }
  };

  const handleReject = async (proposalId: string) => {
    if (!agentId) return;
    setProcessingId(proposalId);
    setError(null);
    try {
      await intelligenceClient.identity.rejectProposal(proposalId);
      // Refresh proposals
      const pendingProposals = await intelligenceClient.identity.getPendingProposals(agentId);
      setProposals(pendingProposals);
    } catch (err) {
      console.error('[IdentityChangeProposal] Failed to reject:', err);
      setError('拒绝失败');
    } finally {
      setProcessingId(null);
    }
  };

  const handleRestore = async (snapshotId: string) => {
    if (!agentId) return;
    setProcessingId(snapshotId);
    setError(null);
    try {
      await intelligenceClient.identity.restoreSnapshot(agentId, snapshotId);
      // Refresh snapshots
      const agentSnapshots = await intelligenceClient.identity.getSnapshots(agentId, 10);
      setSnapshots(agentSnapshots);
    } catch (err) {
      console.error('[IdentityChangeProposal] Failed to restore:', err);
      setError('恢复失败');
    } finally {
      setProcessingId(null);
    }
  };

  if (!agentId) {
    return (
      <div className="text-center py-8 text-gray-500 dark:text-gray-400">
        <FileText className="w-8 h-8 mx-auto mb-2 opacity-50" />
        <p className="text-sm">请先选择一个 Agent</p>
      </div>
    );
  }

  if (loading) {
    return (
      <div className="text-center py-8 text-gray-500 dark:text-gray-400">
        <div className="animate-pulse">加载中...</div>
      </div>
    );
  }

  return (
    <div className="space-y-6">
      {/* Error */}
      {error && (
        <div className="flex items-center gap-2 p-3 rounded-lg bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-300 text-sm">
          <AlertCircle className="w-4 h-4" />
          {error}
        </div>
      )}

      {/* Pending Proposals */}
      <div>
        <h3 className="text-sm font-semibold text-gray-900 dark:text-gray-100 mb-3 flex items-center gap-2">
          <Sparkles className="w-4 h-4 text-orange-500" />
          待审批提案
          {proposals.length > 0 && (
            <Badge variant="warning" className="text-xs">
              {proposals.length}
            </Badge>
          )}
        </h3>

        {proposals.length === 0 ? (
          <div className="text-center py-6 text-gray-500 dark:text-gray-400 text-sm bg-gray-50 dark:bg-gray-800/50 rounded-lg border border-gray-100 dark:border-gray-700">
            暂无待审批的人格变更提案
          </div>
        ) : (
          <div className="space-y-3">
            <AnimatePresence>
              {proposals.map((proposal) => (
                <ProposalCard
                  key={proposal.id}
                  proposal={proposal}
                  onApprove={() => handleApprove(proposal.id)}
                  onReject={() => handleReject(proposal.id)}
                  isProcessing={processingId === proposal.id}
                />
              ))}
            </AnimatePresence>
          </div>
        )}
      </div>

      {/* Evolution History */}
      <div>
        <h3 className="text-sm font-semibold text-gray-900 dark:text-gray-100 mb-3 flex items-center gap-2">
          <History className="w-4 h-4 text-gray-500" />
          演化历史
        </h3>

        {snapshots.length === 0 ? (
          <div className="text-center py-6 text-gray-500 dark:text-gray-400 text-sm bg-gray-50 dark:bg-gray-800/50 rounded-lg border border-gray-100 dark:border-gray-700">
            暂无演化历史
          </div>
        ) : (
          <div className="space-y-2">
            {snapshots.map((snapshot) => (
              <HistoryItem
                key={snapshot.id}
                snapshot={snapshot}
                onRestore={() => handleRestore(snapshot.id)}
                isRestoring={processingId === snapshot.id}
              />
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

// === Helper ===

function getTimeAgo(timestamp: string): string {
  const now = Date.now();
  const then = new Date(timestamp).getTime();
  const diff = now - then;

  if (diff < 60000) return '刚刚';
  if (diff < 3600000) return `${Math.floor(diff / 60000)} 分钟前`;
  if (diff < 86400000) return `${Math.floor(diff / 3600000)} 小时前`;
  if (diff < 604800000) return `${Math.floor(diff / 86400000)} 天前`;
  return new Date(timestamp).toLocaleDateString('zh-CN');
}

export default IdentityChangeProposalPanel;
