/**
 * OnboardingWizard — 首次使用引导向导
 */

import { useState, useEffect } from 'react';
import { Dialog, DialogContent, Button, TextField, Select, MenuItem, Stepper, Step, StepLabel, Box, Typography, Stack, FormControl, InputLabel, IconButton, InputAdornment } from '@mui/material';
import { ArrowRight, ArrowLeft, FolderOpen, Play, CheckCircle, Eye, EyeOff } from 'lucide-react';
import { useUIStore } from '@renderer/stores/ui-store';
import { useAgentStore } from '@renderer/stores/agent-store';

const STEPS = ['欢迎', '配置 LLM', '自定义 Agent', '工作空间', '开始使用'];

// #48 修复: Onboarding 进度持久化 key
const ONBOARDING_PROGRESS_KEY = 'onboarding_progress';

export function OnboardingWizard(): React.JSX.Element | null {
  const onboardingCompleted = useUIStore((s) => s.onboardingCompleted);
  const setOnboardingCompleted = useUIStore((s) => s.setOnboardingCompleted);
  const [step, setStep] = useState(0);
  const [provider, setProvider] = useState('');
  const [baseURL, setBaseURL] = useState('');
  const [model, setModel] = useState('');
  const [apiKey, setApiKey] = useState('');
  const [showKey, setShowKey] = useState(false);
  const [workspacePath, setWorkspacePath] = useState('');
  // 上下文窗口（联动 Provider：ollama 可空=由模型决定；其他 provider 默认值见 DEFAULT_CTX）
  const [contextWindow, setContextWindow] = useState<number | null>(null);

  // #48 修复: 启动时从 localStorage 恢复未完成的引导进度，避免中途退出后需重新填写
  // 注意: apiKey 属于敏感信息，不持久化到 localStorage，恢复时需用户重新输入
  useEffect(() => {
    try {
      const saved = localStorage.getItem(ONBOARDING_PROGRESS_KEY);
      if (!saved) return;
      const p = JSON.parse(saved) as {
        step?: number; provider?: string; baseURL?: string;
        model?: string; workspacePath?: string;
        contextWindow?: number | null;
      };
      if (typeof p.step === 'number' && p.step >= 0 && p.step < STEPS.length) setStep(p.step);
      if (typeof p.provider === 'string') setProvider(p.provider);
      if (typeof p.baseURL === 'string') setBaseURL(p.baseURL);
      if (typeof p.model === 'string') setModel(p.model);
      if (typeof p.workspacePath === 'string') setWorkspacePath(p.workspacePath);
      if (p.contextWindow !== undefined) setContextWindow(p.contextWindow);
      // 审查修复: 恢复后如果 provider 需要 apiKey 但 apiKey 为空（未持久化），
      // 回退到步骤 1（配置 LLM）让用户重新输入 apiKey，避免配置不完整
      // ollama 不需要 apiKey
      if (p.provider && p.provider !== 'ollama' && p.step && p.step >= 2) {
        setStep(1);
      }
    } catch {
      // 解析失败忽略，使用默认值
    }
  }, []);

  // #48 修复: 每步完成后保存进度到 localStorage，中途退出（关闭窗口/刷新）可恢复
  // 注意: 不保存 apiKey（敏感信息不写入 localStorage）
  useEffect(() => {
    try {
      localStorage.setItem(ONBOARDING_PROGRESS_KEY, JSON.stringify({
        step, provider, baseURL, model, workspacePath, contextWindow,
      }));
    } catch {
      // 写入失败（如隐私模式）忽略
    }
  }, [step, provider, baseURL, model, workspacePath, contextWindow]);

  if (onboardingCompleted) return null;

  // 各 Provider 上下文窗口默认值（与 SettingsModal 保持一致）
  // ollama 返回 null（由模型决定），其他 provider 返回正整数
  const DEFAULT_CTX: Record<string, number | null> = {
    deepseek: 1_000_000,
    agnes: 1_000_000,
    mimo: 1_000_000,
    ollama: null,
  };
  // 上下文窗口校验：ollama 允许空，最小 512；其他 provider 最小 4096
  const ctxMin = provider === 'ollama' ? 512 : 4096;
  const ctxError =
    contextWindow != null && (!Number.isFinite(contextWindow) || contextWindow < ctxMin);

  const handleNext = async () => {
    if (step < STEPS.length - 1) { setStep(step + 1); return; }
    try {
      if (window.metona?.config?.setBatch) {
        // v0.3.9: 改用批量保存，避免并行 config.set 中间态触发 reloadAdapter 失败
        // 旧实现问题：Promise.allSettled 并行 6 个 config.set，
        //   - llm.provider 写入会清空 llm.apiKey（与 llm.apiKey 写入竞态）
        //   - reloadAdapter 被调用 4 次，中间态必然失败
        //   - 代码只检查 status === 'rejected'，完全忽略 { success: false } 的情况
        //   - 实际配置失败但前端显示成功并关闭向导
        const entries: Array<{ key: string; value: unknown }> = [];
        if (provider.trim()) entries.push({ key: 'llm.provider', value: provider.trim() });
        if (baseURL.trim()) entries.push({ key: 'llm.baseURL', value: baseURL.trim() });
        if (model.trim()) entries.push({ key: 'llm.model', value: model.trim() });
        if (apiKey.trim()) entries.push({ key: 'llm.apiKey', value: apiKey.trim() });
        if (workspacePath.trim()) entries.push({ key: 'workspace.path', value: workspacePath.trim() });
        // 上下文窗口：根据 Provider 落库到对应 key
        // - ollama: ollama.numCtx（允许 null=由模型决定）
        // - deepseek/agnes/mimo: {provider}.contextWindow（必须有值且 >= 4096）
        if (provider === 'ollama') {
          entries.push({ key: 'ollama.numCtx', value: contextWindow });
        } else if (provider && contextWindow != null && contextWindow >= 4096) {
          entries.push({ key: `${provider}.contextWindow`, value: contextWindow });
        }
        entries.push({ key: 'onboarding.completed', value: true });

        const r = await window.metona.config.setBatch(entries);
        if (r && !r.success) {
          console.error('[OnboardingWizard]', 'Batch config save failed:', r.error);
          import('@metona-team/metona-toast').then((mod) => mod.default.error(r.error ?? '配置保存失败，请重试')).catch(() => {});
          return;
        }
        useAgentStore.getState().setProvider(provider.trim() || 'deepseek', model.trim() || '');
        // 同步 contextWindow 到 Agent Store（与 SettingsModal 行为一致）
        if (contextWindow != null && contextWindow >= ctxMin) {
          useAgentStore.setState({ contextWindow });
        }
        // P1-6 修复: Onboarding 完成后标记配置已加载
        useAgentStore.getState().setConfigLoaded(true);
      }
      setOnboardingCompleted(true);
      // #48 修复: 引导完成后清理 localStorage 进度，下次启动不再恢复
      try { localStorage.removeItem(ONBOARDING_PROGRESS_KEY); } catch { /* ignore */ }
    } catch (err) {
      console.error('[OnboardingWizard]', 'Failed to save configuration:', err);
      // 用户主动操作失败必须有反馈，否则向导不关闭、用户卡死
      import('@metona-team/metona-toast').then((mod) => mod.default.error(`保存配置失败：${(err as Error).message}`)).catch(() => {});
    }
  };

  return (
    <Dialog open maxWidth="sm" slotProps={{ paper: { sx: { borderRadius: 3, overflow: 'hidden' } } }}>
      <Box sx={{ px: 3, pt: 2, pb: 0 }}>
        <Stepper activeStep={step} alternativeLabel sx={{ '& .MuiStepLabel-label': { fontSize: 11 } }}>
          {STEPS.map((s) => <Step key={s}><StepLabel>{s}</StepLabel></Step>)}
        </Stepper>
      </Box>
      <DialogContent sx={{ minHeight: 280, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
        {step === 0 && (
          <Box sx={{ textAlign: 'center' }}>
            <Box component="img" src="./logo.png" alt="Metona" sx={{ width: 64, height: 64, mx: 'auto', mb: 2, borderRadius: 2 }} />
            <Typography variant="h6" sx={{ mb: 1 }}>欢迎使用 MetonaAI Desktop</Typography>
            <Typography variant="body2" sx={{ color: 'text.secondary', mb: 2 }}>生产级通用 AI Agent 智能体桌面应用，支持多轮对话、工具调用、记忆系统和 MCP 协议集成。</Typography>
            <Typography variant="caption">让我们花 1 分钟完成初始配置。</Typography>
          </Box>
        )}
        {step === 1 && (
          <Box sx={{ width: '100%' }}>
            <Typography variant="h6" sx={{ mb: 2 }}>配置 LLM Provider</Typography>
            <Typography variant="body2" sx={{ color: 'text.secondary', mb: 2 }}>选择 Provider 并填写 API 信息。Base URL 和模型名称支持任意输入。</Typography>
            <Stack spacing={2}>
              <FormControl size="small"><InputLabel>Provider</InputLabel>
                <Select value={provider} label="Provider" onChange={(e) => {
                  const v = e.target.value;
                  setProvider(v);
                  // 联动默认上下文窗口（与 SettingsModal 默认值一致）
                  setContextWindow(DEFAULT_CTX[v] ?? null);
                }}>
                  <MenuItem value="deepseek">DeepSeek</MenuItem>
                  <MenuItem value="agnes">Agnes AI</MenuItem>
                  <MenuItem value="mimo">MiMo (小米)</MenuItem>
                  <MenuItem value="ollama">Ollama (本地)</MenuItem>
                </Select>
              </FormControl>
              <TextField size="small" label="API Base URL" value={baseURL} onChange={(e) => setBaseURL(e.target.value)} placeholder="如 https://api.deepseek.com" />
              <TextField size="small" label="模型名称" value={model} onChange={(e) => setModel(e.target.value)} placeholder="如 deepseek-v4-pro、qwen3:latest" />
              <TextField size="small" label="API Key" type={showKey ? 'text' : 'password'} value={apiKey} onChange={(e) => setApiKey(e.target.value)} placeholder="sk-...（本地模型可留空）"
                slotProps={{ input: { endAdornment: <InputAdornment position="end"><IconButton size="small" onClick={() => setShowKey(!showKey)}>{showKey ? <EyeOff size={14} /> : <Eye size={14} />}</IconButton></InputAdornment> } }}
              />
              <TextField
                size="small"
                label={provider === 'ollama' ? '上下文长度 (num_ctx)' : '上下文窗口 (contextWindow)'}
                type="number"
                value={contextWindow ?? ''}
                onChange={(e) => {
                  const v = e.target.value;
                  setContextWindow(v === '' ? null : Number(v));
                }}
                placeholder={provider === 'ollama' ? '默认由模型决定（如 2048、4096、128000）' : '如 64000、128000、1000000'}
                slotProps={{ htmlInput: { min: ctxMin, step: ctxMin } }}
                error={ctxError}
                helperText={ctxError ? `最小值为 ${ctxMin}` : (provider === 'ollama' ? ' ' : '用于上下文压缩判断，不传给 API')}
              />
            </Stack>
          </Box>
        )}
        {step === 2 && (
          <Box sx={{ width: '100%' }}>
            <Typography variant="h6" sx={{ mb: 2 }}>自定义 Agent</Typography>
            <Typography variant="body2" sx={{ color: 'text.secondary', mb: 2 }}>编辑工作空间中的 SOUL.md 文件来定义 Agent 的身份和性格。</Typography>
            <Box sx={{ px: 2, py: 1.5, borderRadius: 2, bgcolor: 'action.hover', border: '1px solid', borderColor: 'divider', fontSize: 12, color: 'text.secondary' }}>
              <div><strong style={{ color: '#e1e4ed' }}>SOUL.md</strong> — 定义 Agent 的身份、性格、核心价值观</div>
              <div style={{ marginTop: 8, fontSize: 11, opacity: 0.7 }}>此步骤可稍后在工作空间目录中完成。</div>
            </Box>
          </Box>
        )}
        {step === 3 && (
          <Box sx={{ width: '100%' }}>
            <Typography variant="h6" sx={{ mb: 2 }}>工作空间</Typography>
            <Typography variant="body2" sx={{ color: 'text.secondary', mb: 2 }}>选择工作空间目录，或使用默认路径。</Typography>
            <Stack direction="row" spacing={1} sx={{ mb: 2, alignItems: 'center' }}>
              <TextField size="small" value={workspacePath} onChange={(e) => setWorkspacePath(e.target.value)} placeholder="~/MetonaWorkspaces/default/" sx={{ flex: 1 }} />
              <Button variant="outlined" size="small" onClick={async () => {
                if (window.metona?.app?.selectFolder) {
                  try {
                    const r = await window.metona.app.selectFolder(workspacePath || undefined);
                    if (!r.canceled && r.path) setWorkspacePath(r.path);
                  } catch (err) {
                    console.error('[OnboardingWizard]', err);
                    import('@metona-team/metona-toast').then((mod) => mod.default.error('选择文件夹失败')).catch(() => {});
                  }
                }
              }}>选择文件夹</Button>
            </Stack>
            <Typography variant="caption" sx={{ color: 'text.secondary' }}>包含 SOUL.md、MEMORY.md 两个必需文件，首次打开时自动创建。</Typography>
          </Box>
        )}
        {step === 4 && (
          <Box sx={{ textAlign: 'center' }}>
            <CheckCircle size={48} style={{ color: '#34d399', margin: '0 auto 16px' }} />
            <Typography variant="h6" sx={{ mb: 1 }}>配置完成！</Typography>
            <Typography variant="body2" sx={{ color: 'text.secondary', mb: 1 }}>MetonaAI Desktop 已准备就绪。开始与你的 AI Agent 对话吧！</Typography>
            <Typography variant="caption">按 Ctrl+Enter 发送消息，输入 / 查看命令列表</Typography>
          </Box>
        )}
      </DialogContent>
      <Box sx={{ display: 'flex', justifyContent: 'space-between', px: 3, py: 1.5, borderTop: 1, borderColor: 'divider' }}>
        <Button startIcon={<ArrowLeft size={12} />} onClick={() => setStep(step - 1)} disabled={step === 0} size="small" sx={{ color: 'text.secondary' }}>上一步</Button>
        <Button variant="contained" endIcon={step < STEPS.length - 1 ? <ArrowRight size={12} /> : undefined} onClick={handleNext} size="small">
          {step === STEPS.length - 1 ? '开始使用' : '下一步'}
        </Button>
      </Box>
    </Dialog>
  );
}
