﻿import { useState, useEffect, useCallback, useRef } from 'react';
import './index.css';
import { Sidebar } from './components/Sidebar';
import { ChatArea } from './components/ChatArea';
import { RightPanel } from './components/RightPanel';
import { ErrorBoundary } from './components/ui/ErrorBoundary';
import { SettingsLayout } from './components/Settings/SettingsLayout';
import { AgentOnboardingWizard } from './components/AgentOnboardingWizard';
import { HandApprovalModal } from './components/HandApprovalModal';
import { TopBar } from './components/TopBar';
import { DetailDrawer } from './components/DetailDrawer';
import { useConnectionStore } from './store/connectionStore';
import { useSaaSStore } from './store/saasStore';
import { useHandStore, type HandRun } from './store/handStore';
import { useChatStore } from './store/chatStore';
import { initializeStores } from './store';
import { getStoredGatewayToken } from './lib/gateway-client';

import { Loader2 } from 'lucide-react';
import { isTauriRuntime, getLocalGatewayStatus, startLocalGateway } from './lib/tauri-gateway';
import { LoginPage } from './components/LoginPage';
import { useOnboarding } from './lib/use-onboarding';
import { intelligenceClient } from './lib/intelligence-client';
import { loadEmbeddingConfig, loadEmbeddingApiKey } from './lib/embedding-client';
import { invoke } from '@tauri-apps/api/core';
import { useProposalNotifications, ProposalNotificationHandler } from './lib/useProposalNotifications';
import { useToast } from './components/ui/Toast';
import type { Clone } from './store/agentStore';
import { createLogger } from './lib/logger';
import { startOfflineMonitor } from './store/offlineStore';
import { useUIModeStore } from './store/uiModeStore';
import { SimpleSidebar } from './components/SimpleSidebar';

const log = createLogger('App');

type View = 'main' | 'settings';

// Bootstrap component that ensures ZCLAW is running before rendering main UI
function BootstrapScreen({ status }: { status: string }) {
  return (
    <div className="h-screen flex items-center justify-center bg-gray-50">
      <div className="flex flex-col items-center gap-4">
        <Loader2 className="w-8 h-8 animate-spin text-blue-500" />
        <p className="text-gray-600 text-sm">{status}</p>
      </div>
    </div>
  );
}

function App() {
  const [view, setView] = useState<View>('main');
  const [bootstrapping, setBootstrapping] = useState(true);
  const [bootstrapStatus, setBootstrapStatus] = useState('Initializing...');
  const [showOnboarding, setShowOnboarding] = useState(false);
  const [showDetailDrawer, setShowDetailDrawer] = useState(false);
  const statsSyncRef = useRef<ReturnType<typeof setInterval> | null>(null);

  // Hand Approval state
  const [pendingApprovalRun, setPendingApprovalRun] = useState<HandRun | null>(null);
  const [showApprovalModal, setShowApprovalModal] = useState(false);

  const connect = useConnectionStore((s) => s.connect);
  const isLoggedIn = useSaaSStore((s) => s.isLoggedIn);
  const hands = useHandStore((s) => s.hands);
  const approveHand = useHandStore((s) => s.approveHand);
  const loadHands = useHandStore((s) => s.loadHands);
  const { setCurrentAgent } = useChatStore();
  const { isNeeded: onboardingNeeded, isLoading: onboardingLoading, markCompleted } = useOnboarding();
  const uiMode = useUIModeStore((s) => s.mode);

  // Proposal notifications
  const { toast } = useToast();
  useProposalNotifications(); // Sets up polling for pending proposals

  // Show toast when new proposals are available
  useEffect(() => {
    const handleProposalAvailable = (event: Event) => {
      const customEvent = event as CustomEvent<{ count: number }>;
      const { count } = customEvent.detail;
      toast(`${count} 个新的人格变更提案待审批`, 'info');
    };

    window.addEventListener('zclaw:proposal-available', handleProposalAvailable);
    return () => {
      window.removeEventListener('zclaw:proposal-available', handleProposalAvailable);
    };
  }, [toast]);

  useEffect(() => {
    document.title = 'ZCLAW';
    const stopOfflineMonitor = startOfflineMonitor();
    return () => { stopOfflineMonitor(); };
  }, []);

  // Restore SaaS session from OS keyring on startup (before auth gate)
  const [isRestoring, setIsRestoring] = useState(true);
  useEffect(() => {
    const restore = async () => {
      try {
        await useSaaSStore.getState().restoreSession();
      } catch {
        // Session restore failed — user will see login page
      }
      setIsRestoring(false);
    };
    restore();
  }, []);

  // Watch for Hands that need approval
  useEffect(() => {
    const handsNeedingApproval = hands.filter(h => h.status === 'needs_approval');
    if (handsNeedingApproval.length > 0 && !showApprovalModal) {
      // Find the first hand with needs_approval and create a pending run
      const hand = handsNeedingApproval[0];
      if (hand.currentRunId) {
        setPendingApprovalRun({
          runId: hand.currentRunId,
          status: 'needs_approval',
          startedAt: new Date().toISOString(),
        });
        setShowApprovalModal(true);
      }
    }
  }, [hands, showApprovalModal]);

  // Handle approval/rejection of Hand runs
  const handleApproveHand = useCallback(async (runId: string) => {
    // Find the hand that owns this run
    const hand = hands.find(h => h.currentRunId === runId);
    if (!hand) return;

    await approveHand(hand.id, runId, true);
    await loadHands();
    setShowApprovalModal(false);
    setPendingApprovalRun(null);
  }, [hands, approveHand, loadHands]);

  const handleRejectHand = useCallback(async (runId: string, reason: string) => {
    // Find the hand that owns this run
    const hand = hands.find(h => h.currentRunId === runId);
    if (!hand) return;

    await approveHand(hand.id, runId, false, reason);
    await loadHands();
    setShowApprovalModal(false);
    setPendingApprovalRun(null);
  }, [hands, approveHand, loadHands]);

  const handleCloseApprovalModal = useCallback(() => {
    setShowApprovalModal(false);
    // Don't clear pendingApprovalRun - keep it for reference
  }, []);

  // Bootstrap: Start ZCLAW Gateway before rendering main UI
  useEffect(() => {
    let mounted = true;

    const bootstrap = async () => {
      // 未登录时不启动 bootstrap，直接结束 loading
      if (!useSaaSStore.getState().isLoggedIn) {
        setBootstrapping(false);
        return;
      }

      try {
        // Step 1: Check and start local gateway in Tauri environment
        if (isTauriRuntime()) {
          setBootstrapStatus('Checking gateway status...');

          try {
            const status = await getLocalGatewayStatus();
            const isRunning = status.portStatus === 'busy' || status.listenerPids.length > 0;

            if (!isRunning && status.cliAvailable) {
              setBootstrapStatus('Starting ZCLAW Gateway...');
              log.debug('Local gateway not running, auto-starting...');

            await startLocalGateway();

            // Wait for gateway to be ready
            await new Promise(resolve => setTimeout(resolve, 2000));
            log.debug('Local gateway started');
          } else if (isRunning) {
            log.debug('Local gateway already running');
          }
        } catch (err) {
          log.warn('Failed to check/start local gateway:', err);
        }
      }

      if (!mounted) return;

      // Step 2: Connect to gateway
      setBootstrapStatus('Connecting to gateway...');
      const gatewayToken = getStoredGatewayToken();
      await connect(undefined, gatewayToken);

      if (!mounted) return;

      // Step 3: Check if onboarding is needed
      if (onboardingNeeded && !onboardingLoading) {
        setShowOnboarding(true);
      }

      // Step 4: Initialize stores with gateway client
      initializeStores();

      // Step 4.5: Auto-start heartbeat engine for self-evolution
      try {
        const defaultAgentId = 'zclaw-main';
        await intelligenceClient.heartbeat.init(defaultAgentId, {
          enabled: true,
          interval_minutes: 30,
          quiet_hours_start: '22:00',
          quiet_hours_end: '08:00',
          notify_channel: 'ui',
          proactivity_level: 'standard',
          max_alerts_per_tick: 5,
        });

        // Sync memory stats to heartbeat engine
        try {
          const stats = await intelligenceClient.memory.stats();
          const taskCount = stats.byType?.['task'] || 0;
          await intelligenceClient.heartbeat.updateMemoryStats(
            defaultAgentId,
            taskCount,
            stats.totalEntries,
            stats.storageSizeBytes
          );
          log.debug('Memory stats synced to heartbeat engine');
        } catch (statsErr) {
          log.warn('Failed to sync memory stats:', statsErr);
        }

        await intelligenceClient.heartbeat.start(defaultAgentId);
        log.debug('Heartbeat engine started for self-evolution');

        // Set up periodic memory stats sync (every 5 minutes)
        const MEMORY_STATS_SYNC_INTERVAL = 5 * 60 * 1000;
        const statsSyncInterval = setInterval(async () => {
          try {
            const stats = await intelligenceClient.memory.stats();
            const taskCount = stats.byType?.['task'] || 0;
            await intelligenceClient.heartbeat.updateMemoryStats(
              defaultAgentId,
              taskCount,
              stats.totalEntries,
              stats.storageSizeBytes
            );
            log.debug('Memory stats synced (periodic)');
          } catch (err) {
            log.warn('Periodic memory stats sync failed:', err);
          }
        }, MEMORY_STATS_SYNC_INTERVAL);

        // Store interval for cleanup via ref
        statsSyncRef.current = statsSyncInterval;
      } catch (err) {
        log.warn('Failed to start heartbeat engine:', err);
        // Non-critical, continue without heartbeat
      }

      // Step 5: Restore embedding config to Rust backend (Tauri-only)
      if (isTauriRuntime()) {
        try {
          // Migrate plaintext embedding apiKey to secure storage if present
          try {
            const embStored = localStorage.getItem('zclaw-embedding-config');
            if (embStored) {
              const embParsed = JSON.parse(embStored);
              if (embParsed.apiKey && embParsed.apiKey.trim()) {
                const { saveEmbeddingApiKey } = await import('./lib/embedding-client');
                const { secureStorage } = await import('./lib/secure-storage');
                // Only migrate if not already in secure storage
                const existing = await secureStorage.get('zclaw-secure-embedding-apikey');
                if (!existing) {
                  await saveEmbeddingApiKey(embParsed.apiKey);
                }
                // Strip apiKey from localStorage
                const { apiKey: _, ...stripped } = embParsed;
                localStorage.setItem('zclaw-embedding-config', JSON.stringify(stripped));
              }
            }
          } catch { /* migration failure is non-critical */ }

          const embConfig = loadEmbeddingConfig();
          const embApiKey = await loadEmbeddingApiKey();
          if (embConfig.enabled && embConfig.provider !== 'local' && embApiKey) {
            setBootstrapStatus('Restoring embedding configuration...');
            await invoke('viking_configure_embedding', {
              provider: embConfig.provider,
              apiKey: embApiKey,
              model: embConfig.model || undefined,
              endpoint: embConfig.endpoint || undefined,
            });
            log.debug('Embedding configuration restored to backend');
          }
        } catch (embErr) {
          log.warn('Failed to restore embedding config:', embErr);
          // Non-critical, semantic search will fall back to TF-IDF
        }

        // Step 5b: Configure summary driver using active LLM (for L0/L1 generation)
        try {
          const { getDefaultModelConfigAsync, migrateModelApiKeysToSecureStorage } = await import('./store/connectionStore');
          // Migrate any plaintext API keys to secure storage (idempotent)
          await migrateModelApiKeysToSecureStorage();
          const modelConfig = await getDefaultModelConfigAsync();
          if (modelConfig && modelConfig.apiKey && modelConfig.baseUrl) {
            setBootstrapStatus('Configuring summary driver...');
            await invoke('viking_configure_summary_driver', {
              endpoint: modelConfig.baseUrl,
              apiKey: modelConfig.apiKey,
              model: modelConfig.model || undefined,
            });
            log.debug('Summary driver configured with active LLM');
          }
        } catch (sumErr) {
          log.warn('Failed to configure summary driver:', sumErr);
          // Non-critical, summaries won't be auto-generated
        }
      }

      // Step 6: Bootstrap complete
      setBootstrapping(false);
    } catch (err) {
      log.error('Bootstrap failed:', err);
      // Still allow app to load, connection status will show error
      setBootstrapping(false);
    }
  };

    bootstrap();

    return () => {
      mounted = false;
      // Clean up periodic stats sync interval
      if (statsSyncRef.current) {
        clearInterval(statsSyncRef.current);
      }
    };
  }, [connect, onboardingNeeded, onboardingLoading, isLoggedIn]);

  // Handle onboarding completion
  const handleOnboardingSuccess = (clone: Clone) => {
    markCompleted({
      userName: clone.userName || 'User',
      userRole: clone.userRole,
    });
    setCurrentAgent({
      id: clone.id,
      name: clone.name,
      icon: clone.emoji || '🦞',
      color: 'bg-gradient-to-br from-orange-500 to-red-500',
      lastMessage: clone.role || 'New Agent',
      time: '',
    });
    setShowOnboarding(false);

    // Auto-trigger first Hand based on industry template
    const templateId = clone.source_template_id || '';
    const industryQueries: Record<string, { hand: string; action: string; query: string }> = {
      'edu-teacher-001': { hand: 'researcher', action: 'report', query: '帮我研究2026年教育数字化转型趋势，包括AI教学工具的最新进展' },
      'healthcare-admin-001': { hand: 'collector', action: 'collect', query: '帮我采集最新的医疗政策文件摘要，重点关注基层医疗改革方向' },
      'design-shantou-001': { hand: 'researcher', action: 'report', query: '帮我研究2026年服装设计流行趋势，包括色彩、面料和款式创新' },
    };
    const task = industryQueries[templateId];
    if (task) {
      // Delay slightly to let UI settle
      setTimeout(() => {
        useHandStore.getState().triggerHand(task.hand, {
          action: task.action,
          query: { query: task.query },
        }).catch(() => {
          // Non-critical — user can trigger manually
        });
      }, 2000);
    }
  };

  // 登录门禁 — 必须登录才能使用
  if (isRestoring) {
    return <BootstrapScreen status="Restoring session..." />;
  }
  if (!isLoggedIn) {
    return <LoginPage />;
  }

  if (view === 'settings') {
    return <SettingsLayout onBack={() => setView('main')} />;
  }

  // Show bootstrap screen while starting gateway
  if (bootstrapping) {
    return <BootstrapScreen status={bootstrapStatus} />;
  }

  // Show onboarding wizard for first-time users
  if (showOnboarding) {
    return (
      <AgentOnboardingWizard
        isOpen={true}
        onClose={async () => {
          // Skip onboarding but still create a default agent with default personality
          try {
            const { getGatewayClient } = await import('./lib/gateway-client');
            const client = getGatewayClient();
            if (client) {
              // Create default agent with versatile assistant personality
              const defaultAgent = await client.createClone({
                name: '全能助手',
                role: '全能型 AI 助手',
                nickname: '小龙',
                emoji: '🦞',
                personality: 'friendly',
                scenarios: ['coding', 'writing', 'research', 'product', 'data'],
                userName: 'User',
                userRole: 'user',
                communicationStyle: '亲切、耐心、善解人意，用易懂的语言解释复杂概念',
              });

              if (defaultAgent?.clone) {
                setCurrentAgent({
                  id: defaultAgent.clone.id,
                  name: defaultAgent.clone.name,
                  icon: defaultAgent.clone.emoji || '🦞',
                  color: 'bg-gradient-to-br from-orange-500 to-red-500',
                  lastMessage: defaultAgent.clone.role || '全能型 AI 助手',
                  time: '',
                });
              }
            }
          } catch (err) {
            log.warn('Failed to create default agent on skip:', err);
          }

          // Mark onboarding as completed
          markCompleted({
            userName: 'User',
            userRole: 'user',
          });
          setShowOnboarding(false);
        }}
        onSuccess={handleOnboardingSuccess}
      />
    );
  }

  // Simple mode: sidebar + chat + detail drawer (Trae Solo style)
  if (uiMode === 'simple') {
    return (
      <div className="h-screen flex overflow-hidden text-gray-800 text-sm bg-white dark:bg-gray-950">
        {/* 简洁侧边栏: 对话 + 行业资讯 */}
        <SimpleSidebar
          onOpenSettings={() => setView('settings')}
          onToggleMode={() => useUIModeStore.getState().setMode('professional')}
        />

        {/* 主聊天区域 */}
        <div className="flex-1 flex flex-col overflow-hidden">
          <ErrorBoundary fallback={<div className="flex-1 flex items-center justify-center text-gray-500">聊天区域加载失败</div>}>
            <ChatArea compact onOpenDetail={() => setShowDetailDrawer(true)} />
          </ErrorBoundary>
        </div>

        {/* 详情抽屉 - 简洁模式仅 状态/Agent/管家 */}
        <DetailDrawer
          open={showDetailDrawer}
          onClose={() => setShowDetailDrawer(false)}
          title="详情"
        >
          <ErrorBoundary fallback={<div className="p-6 text-center text-gray-500">详情面板加载失败</div>}>
            <RightPanel simpleMode />
          </ErrorBoundary>
        </DetailDrawer>

        {/* Hand Approval Modal (global) */}
        <HandApprovalModal
          handRun={pendingApprovalRun}
          isOpen={showApprovalModal}
          onApprove={handleApproveHand}
          onReject={handleRejectHand}
          onClose={handleCloseApprovalModal}
        />

        {/* Proposal Notifications Handler */}
        <ProposalNotificationHandler />
      </div>
    );
  }

  // Professional mode: three-column layout (default)
  return (
    <div className="h-screen flex overflow-hidden text-gray-800 text-sm bg-white dark:bg-gray-950">
      {/* 左侧边栏 */}
      <Sidebar
        onOpenSettings={() => setView('settings')}
      />

      {/* 主内容区 */}
      <div className="flex-1 flex flex-col overflow-hidden">
        {/* 顶部工具栏 */}
        <TopBar
          title="ZCLAW"
          onOpenDetail={() => setShowDetailDrawer(true)}
        />

        {/* 聊天区域 */}
        <ErrorBoundary fallback={<div className="flex-1 flex items-center justify-center text-gray-500">聊天区域加载失败，请刷新页面</div>}>
          <ChatArea />
        </ErrorBoundary>
      </div>

      {/* 详情抽屉 - 按需显示 */}
      <DetailDrawer
        open={showDetailDrawer}
        onClose={() => setShowDetailDrawer(false)}
        title="详情"
      >
        <ErrorBoundary fallback={<div className="p-6 text-center text-gray-500">详情面板加载失败</div>}>
          <RightPanel />
        </ErrorBoundary>
      </DetailDrawer>

      {/* Hand Approval Modal (global) */}
      <HandApprovalModal
        handRun={pendingApprovalRun}
        isOpen={showApprovalModal}
        onApprove={handleApproveHand}
        onReject={handleRejectHand}
        onClose={handleCloseApprovalModal}
      />

      {/* Proposal Notifications Handler */}
      <ProposalNotificationHandler />
    </div>
  );
}

export default App;


