/**
 * ReflectionLog - Self-reflection history and identity change approval UI
 *
 * Displays:
 * - Reflection history (patterns, improvements)
 * - Pending identity change proposals
 * - Approve/reject identity modifications
 * - Manual reflection trigger
 *
 * Part of ZCLAW L4 Self-Evolution capability.
 */

import { useState, useEffect, useCallback, useMemo } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import {
  Brain,
  Check,
  X,
  ChevronDown,
  ChevronRight,
  RefreshCw,
  AlertTriangle,
  TrendingUp,
  TrendingDown,
  Minus,
  FileText,
  History,
  Play,
  Settings,
} from 'lucide-react';
import {
  intelligenceClient,
  type ReflectionResult,
  type IdentityChangeProposal,
  type ReflectionConfig,
  type PatternObservation,
  type ImprovementSuggestion,
} from '../lib/intelligence-client';

// === Config Persistence ===

const REFLECTION_CONFIG_KEY = 'zclaw-reflection-config';

const DEFAULT_CONFIG: ReflectionConfig = {
  trigger_after_conversations: 5,
  allow_soul_modification: true,
  require_approval: true,
  use_llm: true,
  llm_fallback_to_rules: true,
};

function loadConfig(): ReflectionConfig {
  try {
    const stored = localStorage.getItem(REFLECTION_CONFIG_KEY);
    if (stored) {
      const parsed = JSON.parse(stored);
      return { ...DEFAULT_CONFIG, ...parsed };
    }
  } catch {
    console.warn('[ReflectionLog] Failed to load config from localStorage');
  }
  return DEFAULT_CONFIG;
}

function saveConfig(config: ReflectionConfig): void {
  try {
    localStorage.setItem(REFLECTION_CONFIG_KEY, JSON.stringify(config));
  } catch {
    console.warn('[ReflectionLog] Failed to save config to localStorage');
  }
}

// === Types ===

interface ReflectionLogProps {
  className?: string;
  agentId?: string;
  onProposalApprove?: (proposal: IdentityChangeProposal) => void;
  onProposalReject?: (proposal: IdentityChangeProposal) => void;
}

// === Sentiment Config ===

const SENTIMENT_CONFIG: Record<string, { icon: typeof TrendingUp; color: string; bgColor: string }> = {
  positive: {
    icon: TrendingUp,
    color: 'text-green-600 dark:text-green-400',
    bgColor: 'bg-green-100 dark:bg-green-900/30',
  },
  negative: {
    icon: TrendingDown,
    color: 'text-red-600 dark:text-red-400',
    bgColor: 'bg-red-100 dark:bg-red-900/30',
  },
  neutral: {
    icon: Minus,
    color: 'text-gray-600 dark:text-gray-400',
    bgColor: 'bg-gray-100 dark:bg-gray-800',
  },
};

// === Priority Config ===

const PRIORITY_CONFIG: Record<string, { color: string; bgColor: string }> = {
  high: {
    color: 'text-red-600 dark:text-red-400',
    bgColor: 'bg-red-100 dark:bg-red-900/30',
  },
  medium: {
    color: 'text-yellow-600 dark:text-yellow-400',
    bgColor: 'bg-yellow-100 dark:bg-yellow-900/30',
  },
  low: {
    color: 'text-blue-600 dark:text-blue-400',
    bgColor: 'bg-blue-100 dark:bg-blue-900/30',
  },
};

// === Components ===

function SentimentBadge({ sentiment }: { sentiment: string }) {
  const config = SENTIMENT_CONFIG[sentiment] || SENTIMENT_CONFIG.neutral;
  const Icon = config.icon;
  return (
    <span
      className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium ${config.bgColor} ${config.color}`}
    >
      <Icon className="w-3 h-3" />
      {sentiment === 'positive' ? '积极' : sentiment === 'negative' ? '消极' : '中性'}
    </span>
  );
}

function PriorityBadge({ priority }: { priority: string }) {
  const config = PRIORITY_CONFIG[priority] || PRIORITY_CONFIG.medium;
  return (
    <span
      className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ${config.bgColor} ${config.color}`}
    >
      {priority === 'high' ? '高' : priority === 'medium' ? '中' : '低'}
    </span>
  );
}

function PatternCard({ pattern }: { pattern: PatternObservation }) {
  const [expanded, setExpanded] = useState(false);

  return (
    <div className="border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden">
      <button
        onClick={() => setExpanded(!expanded)}
        className="w-full flex items-start gap-3 p-3 hover:bg-gray-50 dark:hover:bg-gray-800/30 transition-colors text-left"
      >
        <SentimentBadge sentiment={pattern.sentiment} />
        <div className="flex-1 min-w-0">
          <p className="text-sm text-gray-900 dark:text-gray-100">{pattern.observation}</p>
          <p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
            出现频率: {pattern.frequency} 次
          </p>
        </div>
        {expanded ? (
          <ChevronDown className="w-4 h-4 text-gray-400 flex-shrink-0" />
        ) : (
          <ChevronRight className="w-4 h-4 text-gray-400 flex-shrink-0" />
        )}
      </button>

      <AnimatePresence>
        {expanded && pattern.evidence.length > 0 && (
          <motion.div
            initial={{ height: 0, opacity: 0 }}
            animate={{ height: 'auto', opacity: 1 }}
            exit={{ height: 0, opacity: 0 }}
            className="border-t border-gray-200 dark:border-gray-700 p-3 bg-gray-50 dark:bg-gray-800/30"
          >
            <h5 className="text-xs font-medium text-gray-500 dark:text-gray-400 mb-2">证据</h5>
            <ul className="space-y-1">
              {pattern.evidence.map((ev, i) => (
                <li key={i} className="text-xs text-gray-600 dark:text-gray-300 pl-2 border-l-2 border-gray-300 dark:border-gray-600">
                  {ev}
                </li>
              ))}
            </ul>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
}

function ImprovementCard({ improvement }: { improvement: ImprovementSuggestion }) {
  return (
    <div className="flex items-start gap-3 p-3 border border-gray-200 dark:border-gray-700 rounded-lg">
      <div className="flex-1 min-w-0">
        <div className="flex items-center gap-2 mb-1">
          <span className="text-sm font-medium text-gray-900 dark:text-gray-100">
            {improvement.area}
          </span>
          <PriorityBadge priority={improvement.priority} />
        </div>
        <p className="text-sm text-gray-600 dark:text-gray-300">{improvement.suggestion}</p>
      </div>
    </div>
  );
}

function ProposalCard({
  proposal,
  onApprove,
  onReject,
}: {
  proposal: IdentityChangeProposal;
  onApprove: () => void;
  onReject: () => void;
}) {
  const [expanded, setExpanded] = useState(false);

  const fileName = proposal.file.split('/').pop() || proposal.file;
  const fileType = fileName.toLowerCase().replace('.md', '').toUpperCase();

  return (
    <div className="border border-yellow-300 dark:border-yellow-700 rounded-lg overflow-hidden bg-yellow-50 dark:bg-yellow-900/20">
      <div className="flex items-center gap-3 p-3">
        <div className="w-8 h-8 rounded-lg bg-yellow-100 dark:bg-yellow-800 flex items-center justify-center">
          <FileText className="w-4 h-4 text-yellow-600 dark:text-yellow-400" />
        </div>
        <div className="flex-1 min-w-0">
          <div className="flex items-center gap-2">
            <span className="text-sm font-medium text-yellow-800 dark:text-yellow-200">
              {fileType} 变更提议
            </span>
            <span className="px-1.5 py-0.5 text-xs bg-yellow-200 dark:bg-yellow-800 text-yellow-700 dark:text-yellow-300 rounded">
              待审批
            </span>
          </div>
          <p className="text-xs text-yellow-600 dark:text-yellow-400 truncate">
            {proposal.reason}
          </p>
        </div>
        <button
          onClick={() => setExpanded(!expanded)}
          className="p-1 text-yellow-600 dark:text-yellow-400 hover:bg-yellow-100 dark:hover:bg-yellow-800 rounded"
        >
          {expanded ? (
            <ChevronDown className="w-4 h-4" />
          ) : (
            <ChevronRight className="w-4 h-4" />
          )}
        </button>
      </div>

      <AnimatePresence>
        {expanded && (
          <motion.div
            initial={{ height: 0, opacity: 0 }}
            animate={{ height: 'auto', opacity: 1 }}
            exit={{ height: 0, opacity: 0 }}
            className="border-t border-yellow-200 dark:border-yellow-700"
          >
            <div className="p-3 space-y-3">
              <div>
                <h5 className="text-xs font-medium text-yellow-700 dark:text-yellow-300 mb-1">
                  当前内容
                </h5>
                <pre className="text-xs text-gray-600 dark:text-gray-300 bg-white dark:bg-gray-800 p-2 rounded overflow-x-auto whitespace-pre-wrap">
                  {proposal.current_content.slice(0, 500)}
                  {proposal.current_content.length > 500 && '...'}
                </pre>
              </div>
              <div>
                <h5 className="text-xs font-medium text-yellow-700 dark:text-yellow-300 mb-1">
                  建议内容
                </h5>
                <pre className="text-xs text-gray-600 dark:text-gray-300 bg-white dark:bg-gray-800 p-2 rounded overflow-x-auto whitespace-pre-wrap">
                  {proposal.suggested_content.slice(0, 500)}
                  {proposal.suggested_content.length > 500 && '...'}
                </pre>
              </div>
            </div>
          </motion.div>
        )}
      </AnimatePresence>

      <div className="flex justify-end gap-2 p-3 border-t border-yellow-200 dark:border-yellow-700">
        <button
          onClick={onReject}
          className="flex items-center gap-1 px-3 py-1.5 text-sm text-gray-600 dark:text-gray-400 hover:text-red-600 dark:hover:text-red-400 transition-colors"
        >
          <X className="w-4 h-4" />
          拒绝
        </button>
        <button
          onClick={onApprove}
          className="flex items-center gap-1 px-3 py-1.5 text-sm bg-green-500 hover:bg-green-600 text-white rounded-lg transition-colors"
        >
          <Check className="w-4 h-4" />
          批准
        </button>
      </div>
    </div>
  );
}

function ReflectionEntry({
  result,
  isExpanded,
  onToggle,
}: {
  result: ReflectionResult;
  isExpanded: boolean;
  onToggle: () => void;
}) {
  const positivePatterns = result.patterns.filter((p) => p.sentiment === 'positive').length;
  const negativePatterns = result.patterns.filter((p) => p.sentiment === 'negative').length;

  return (
    <div className="border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden">
      <button
        onClick={onToggle}
        className="w-full flex items-center gap-3 p-4 hover:bg-gray-50 dark:hover:bg-gray-800/30 transition-colors text-left"
      >
        <div className="w-10 h-10 rounded-lg bg-purple-100 dark:bg-purple-900/30 flex items-center justify-center">
          <Brain className="w-5 h-5 text-purple-500" />
        </div>
        <div className="flex-1 min-w-0">
          <div className="flex items-center gap-2 mb-1">
            <span className="text-sm font-medium text-gray-900 dark:text-gray-100">
              自我反思
            </span>
            <span className="text-xs text-gray-500 dark:text-gray-400">
              {new Date(result.timestamp).toLocaleString('zh-CN')}
            </span>
          </div>
          <div className="flex items-center gap-3 text-xs">
            <span className="text-green-600 dark:text-green-400">
              {positivePatterns} 积极
            </span>
            <span className="text-red-600 dark:text-red-400">
              {negativePatterns} 消极
            </span>
            <span className="text-gray-500 dark:text-gray-400">
              {result.improvements.length} 建议
            </span>
            {result.identity_proposals.length > 0 && (
              <span className="text-yellow-600 dark:text-yellow-400">
                {result.identity_proposals.length} 变更
              </span>
            )}
          </div>
        </div>
        {isExpanded ? (
          <ChevronDown className="w-4 h-4 text-gray-400" />
        ) : (
          <ChevronRight className="w-4 h-4 text-gray-400" />
        )}
      </button>

      <AnimatePresence>
        {isExpanded && (
          <motion.div
            initial={{ height: 0, opacity: 0 }}
            animate={{ height: 'auto', opacity: 1 }}
            exit={{ height: 0, opacity: 0 }}
            className="border-t border-gray-200 dark:border-gray-700"
          >
            <div className="p-4 space-y-4">
              {/* Patterns */}
              {result.patterns.length > 0 && (
                <div>
                  <h4 className="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider mb-2">
                    行为模式
                  </h4>
                  <div className="space-y-2">
                    {result.patterns.map((pattern, i) => (
                      <PatternCard key={i} pattern={pattern} />
                    ))}
                  </div>
                </div>
              )}

              {/* Improvements */}
              {result.improvements.length > 0 && (
                <div>
                  <h4 className="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider mb-2">
                    改进建议
                  </h4>
                  <div className="space-y-2">
                    {result.improvements.map((improvement, i) => (
                      <ImprovementCard key={i} improvement={improvement} />
                    ))}
                  </div>
                </div>
              )}

              {/* Meta */}
              <div className="flex items-center gap-4 text-xs text-gray-500 dark:text-gray-400 pt-2 border-t border-gray-200 dark:border-gray-700">
                <span>新增记忆: {result.new_memories}</span>
                <span>身份变更提议: {result.identity_proposals.length}</span>
              </div>
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
}

// === Main Component ===

export function ReflectionLog({
  className = '',
  agentId = 'zclaw-main',
  onProposalApprove,
  onProposalReject,
}: ReflectionLogProps) {
  const [history, setHistory] = useState<ReflectionResult[]>([]);
  const [pendingProposals, setPendingProposals] = useState<IdentityChangeProposal[]>([]);
  const [expandedId, setExpandedId] = useState<string | null>(null);
  const [isReflecting, setIsReflecting] = useState(false);
  const [showConfig, setShowConfig] = useState(false);
  const [config, setConfig] = useState<ReflectionConfig>(() => loadConfig());

  // Persist config changes
  useEffect(() => {
    saveConfig(config);
  }, [config]);

  // Load history and pending proposals
  useEffect(() => {
    const loadData = async () => {
      try {
        // Initialize reflection engine with config that allows soul modification
        await intelligenceClient.reflection.init(config);

        const loadedHistory = await intelligenceClient.reflection.getHistory();
        setHistory([...loadedHistory].reverse()); // Most recent first

        const proposals = await intelligenceClient.identity.getPendingProposals(agentId);
        setPendingProposals(proposals);
      } catch (error) {
        console.error('[ReflectionLog] Failed to load data:', error);
      }
    };
    loadData();
  }, [agentId, config]);

  const handleReflect = useCallback(async () => {
    setIsReflecting(true);
    try {
      const result = await intelligenceClient.reflection.reflect(agentId, []);
      setHistory((prev) => [result, ...prev]);

      // Convert reflection identity_proposals to actual identity proposals
      // The reflection result contains proposals that need to be persisted
      if (result.identity_proposals && result.identity_proposals.length > 0) {
        for (const proposal of result.identity_proposals) {
          try {
            // Determine which file to modify based on the field
            const file: 'soul' | 'instructions' =
              proposal.field === 'soul' || proposal.field === 'instructions'
                ? (proposal.field as 'soul' | 'instructions')
                : proposal.field.toLowerCase().includes('soul')
                ? 'soul'
                : 'instructions';

            // Persist the proposal to the identity system
            await intelligenceClient.identity.proposeChange(
              agentId,
              file,
              proposal.proposed_value,
              proposal.reason
            );
          } catch (err) {
            console.warn('[ReflectionLog] Failed to create identity proposal:', err);
          }
        }

        // Refresh pending proposals from the identity system
        const proposals = await intelligenceClient.identity.getPendingProposals(agentId);
        setPendingProposals(proposals);
      }
    } catch (error) {
      console.error('[ReflectionLog] Reflection failed:', error);
    } finally {
      setIsReflecting(false);
    }
  }, [agentId]);

  const handleApproveProposal = useCallback(
    async (proposal: IdentityChangeProposal) => {
      await intelligenceClient.identity.approveProposal(proposal.id);
      setPendingProposals((prev: IdentityChangeProposal[]) => prev.filter((p: IdentityChangeProposal) => p.id !== proposal.id));
      onProposalApprove?.(proposal);
    },
    [onProposalApprove]
  );

  const handleRejectProposal = useCallback(
    async (proposal: IdentityChangeProposal) => {
      await intelligenceClient.identity.rejectProposal(proposal.id);
      setPendingProposals((prev: IdentityChangeProposal[]) => prev.filter((p: IdentityChangeProposal) => p.id !== proposal.id));
      onProposalReject?.(proposal);
    },
    [onProposalReject]
  );

  const stats = useMemo(() => {
    const totalReflections = history.length;
    const totalPatterns = history.reduce((sum: number, r: ReflectionResult) => sum + r.patterns.length, 0);
    const totalImprovements = history.reduce((sum: number, r: ReflectionResult) => sum + r.improvements.length, 0);
    const totalIdentityChanges = history.reduce((sum: number, r: ReflectionResult) => sum + r.identity_proposals.length, 0);
    return { totalReflections, totalPatterns, totalImprovements, totalIdentityChanges };
  }, [history]);

  return (
    <div className={`flex flex-col h-full ${className}`}>
      {/* Header */}
      <div className="flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-700">
        <div className="flex items-center gap-2">
          <Brain className="w-5 h-5 text-purple-500" />
          <h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100">反思日志</h2>
        </div>
        <div className="flex items-center gap-2">
          <button
            onClick={() => setShowConfig(!showConfig)}
            className="p-1.5 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200"
            title="配置"
          >
            <Settings className="w-4 h-4" />
          </button>
          <button
            onClick={handleReflect}
            disabled={isReflecting}
            className="flex items-center gap-1 px-3 py-1.5 text-sm bg-purple-500 hover:bg-purple-600 disabled:bg-gray-300 disabled:cursor-not-allowed text-white rounded-lg transition-colors"
          >
            {isReflecting ? (
              <RefreshCw className="w-4 h-4 animate-spin" />
            ) : (
              <Play className="w-4 h-4" />
            )}
            反思
          </button>
        </div>
      </div>

      {/* Stats Bar */}
      <div className="flex items-center gap-4 px-4 py-2 bg-gray-50 dark:bg-gray-800/50 border-b border-gray-200 dark:border-gray-700 text-xs">
        <span className="text-gray-500 dark:text-gray-400">
          反思: <span className="font-medium text-gray-900 dark:text-gray-100">{stats.totalReflections}</span>
        </span>
        <span className="text-purple-600 dark:text-purple-400">
          模式: <span className="font-medium">{stats.totalPatterns}</span>
        </span>
        <span className="text-blue-600 dark:text-blue-400">
          建议: <span className="font-medium">{stats.totalImprovements}</span>
        </span>
        <span className="text-yellow-600 dark:text-yellow-400">
          变更: <span className="font-medium">{stats.totalIdentityChanges}</span>
        </span>
      </div>

      {/* Config Panel */}
      <AnimatePresence>
        {showConfig && (
          <motion.div
            initial={{ height: 0, opacity: 0 }}
            animate={{ height: 'auto', opacity: 1 }}
            exit={{ height: 0, opacity: 0 }}
            className="border-b border-gray-200 dark:border-gray-700 overflow-hidden"
          >
            <div className="p-4 bg-gray-50 dark:bg-gray-800/50 space-y-3">
              <div className="flex items-center justify-between">
                <span className="text-sm text-gray-700 dark:text-gray-300">对话后触发反思</span>
                <input
                  type="number"
                  min="1"
                  max="20"
                  value={config.trigger_after_conversations || 5}
                  onChange={(e) =>
                    setConfig((prev) => ({ ...prev, trigger_after_conversations: parseInt(e.target.value) || 5 }))
                  }
                  className="w-16 px-2 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100"
                />
              </div>
              <div className="flex items-center justify-between">
                <span className="text-sm text-gray-700 dark:text-gray-300">允许修改 SOUL.md</span>
                <button
                  onClick={() => setConfig((prev) => ({ ...prev, allow_soul_modification: !prev.allow_soul_modification }))}
                  className={`relative w-9 h-5 rounded-full transition-colors ${
                    config.allow_soul_modification ? 'bg-purple-500' : 'bg-gray-300 dark:bg-gray-600'
                  }`}
                >
                  <motion.div
                    animate={{ x: config.allow_soul_modification ? 18 : 0 }}
                    className="absolute top-0.5 left-0.5 w-4 h-4 bg-white rounded-full shadow"
                  />
                </button>
              </div>
              <div className="flex items-center justify-between">
                <span className="text-sm text-gray-700 dark:text-gray-300">变更需审批</span>
                <button
                  onClick={() => setConfig((prev) => ({ ...prev, require_approval: !prev.require_approval }))}
                  className={`relative w-9 h-5 rounded-full transition-colors ${
                    config.require_approval ? 'bg-purple-500' : 'bg-gray-300 dark:bg-gray-600'
                  }`}
                >
                  <motion.div
                    animate={{ x: config.require_approval ? 18 : 0 }}
                    className="absolute top-0.5 left-0.5 w-4 h-4 bg-white rounded-full shadow"
                  />
                </button>
              </div>
            </div>
          </motion.div>
        )}
      </AnimatePresence>

      {/* Content */}
      <div className="flex-1 overflow-y-auto p-4 space-y-4">
        {/* Pending Proposals */}
        {pendingProposals.length > 0 && (
          <div className="space-y-3">
            <h3 className="flex items-center gap-2 text-sm font-medium text-yellow-700 dark:text-yellow-300">
              <AlertTriangle className="w-4 h-4" />
              待审批变更 ({pendingProposals.length})
            </h3>
            {pendingProposals.map((proposal) => (
              <ProposalCard
                key={proposal.id}
                proposal={proposal}
                onApprove={() => handleApproveProposal(proposal)}
                onReject={() => handleRejectProposal(proposal)}
              />
            ))}
          </div>
        )}

        {/* History */}
        <div className="space-y-3">
          <h3 className="flex items-center gap-2 text-sm font-medium text-gray-500 dark:text-gray-400">
            <History className="w-4 h-4" />
            反思历史
          </h3>

          {history.length === 0 ? (
            <div className="flex flex-col items-center justify-center py-8 text-gray-500 dark:text-gray-400">
              <Brain className="w-8 h-8 mb-2 opacity-50" />
              <p className="text-sm">暂无反思记录</p>
              <button
                onClick={handleReflect}
                className="mt-2 text-purple-500 hover:text-purple-600 text-sm"
              >
                触发第一次反思
              </button>
            </div>
          ) : (
            history.map((result) => (
              <ReflectionEntry
                key={result.timestamp}
                result={result}
                isExpanded={expandedId === result.timestamp}
                onToggle={() => setExpandedId((prev) => (prev === result.timestamp ? null : result.timestamp))}
              />
            ))
          )}
        </div>
      </div>
    </div>
  );
}

export default ReflectionLog;
