import React, { useEffect, useState, useCallback, useRef } from 'react';
import {
  App,
  Card,
  Form,
  Input,
  Button,
  Select,
  AutoComplete,
  InputNumber,
  Tag,
  Descriptions,
  Spin,
  Alert,
  Typography,
  Space,
  Steps,
  Switch,
} from 'antd';
import {
  SaveOutlined,
  ApiOutlined,
  CheckCircleOutlined,
  CloseCircleOutlined,
  WarningOutlined,
  ReloadOutlined,
  CloudServerOutlined,
  SafetyOutlined,
  RobotOutlined,
} from '@ant-design/icons';
import api from '../../api';
import { message } from '../../ui/app-message';
import { usePermission } from '../../hooks/usePermission';
import type { AiProvider } from './helpers';
import {
  PROVIDER_OPTIONS,
  PROVIDER_DEFAULTS,
  FIXED_PROVIDERS,
  formatDateTime,
  sourceLabel,
  sourceColor,
  shouldAutoSwapBaseUrl,
  extractErrorMessage,
} from './helpers';
import styles from './index.module.css';

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

interface AiConfigData {
  id: number;
  provider: AiProvider;
  baseUrl: string;
  hasApiKey: boolean;
  hasDatabaseKey: boolean;
  maskedApiKey: string | null;
  keySource: 'database' | 'environment' | 'none';
  defaultModel: string | null;
  enabled: boolean;
  supportsVision: boolean;
  timeoutMs: number;
  reasoningEffort: string | null;
  verified: boolean;
  lastTestedAt: string | null;
  lastTestLatencyMs: number | null;
  createdAt: string;
  updatedAt: string;
}

interface TestResult {
  success: boolean;
  latencyMs: number | null;
  modelCount: number | null;
  modelAvailable: boolean;
  testedAt: string;
  message: string;
}

interface FetchModelsResult {
  success: boolean;
  models: Array<{ id: string }>;
  message?: string;
}

interface ApiResponse<T> {
  success: boolean;
  data: T;
  message?: string;
}

// ---------------------------------------------------------------------------
// Form state — mirrors all form fields, survives Step unmounts
// ---------------------------------------------------------------------------

interface FormValues {
  provider: AiProvider;
  baseUrl: string;
  apiKey: string;
  defaultModel: string;
  timeoutMs: number;
  supportsVision: boolean;
  reasoningEffort: string;
}

const DEFAULT_FORM_VALUES: FormValues = {
  provider: 'DEEPSEEK',
  baseUrl: PROVIDER_DEFAULTS['DEEPSEEK'],
  apiKey: '',
  defaultModel: '',
  timeoutMs: 30000,
  supportsVision: false,
  reasoningEffort: '',
};

// ---------------------------------------------------------------------------
// Step definitions
// ---------------------------------------------------------------------------

const STEP_ITEMS = [
  { title: '服务商', description: '选择 AI 服务商' },
  { title: '密钥', description: '配置 API 密钥' },
  { title: '模型', description: '获取并选择模型' },
  { title: '完成', description: '保存并测试连接' },
];

// ---------------------------------------------------------------------------
// Page Component
// ---------------------------------------------------------------------------

const AiConfigPage: React.FC = () => {
  const { hasPermission } = usePermission();
  const { modal } = App.useApp();
  const [form] = Form.useForm();

  const [currentStep, setCurrentStep] = useState(0);
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [testing, setTesting] = useState(false);
  const [fetchingModels, setFetchingModels] = useState(false);
  const [config, setConfig] = useState<AiConfigData | null>(null);
  const [testResult, setTestResult] = useState<TestResult | null>(null);
  const [modelOptions, setModelOptions] = useState<Array<{ value: string; label: string }>>([]);
  const [error, setError] = useState<string | null>(null);

  // Central form state — survives Step transitions when Form.Items unmount
  const [formValues, setFormValues] = useState<FormValues>(DEFAULT_FORM_VALUES);

  const lastProviderRef = useRef<AiProvider | null>(null);

  const canWrite = hasPermission('ai:config:write');
  const canTest = hasPermission('ai:config:test');
  const canRead = hasPermission('ai:config:read');

  // ── Sync form → state ──

  const handleFormChange = useCallback((_changed: Partial<FormValues>, all: Partial<FormValues>) => {
    setFormValues((prev) => ({ ...prev, ...all }));
  }, []);

  // ── Load config (full) — used on initial mount and after save ──

  const loadConfig = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const res = await api.get<ApiResponse<AiConfigData>>('/ai/config');
      setConfig(res.data);

      const initial: FormValues = {
        provider: res.data.provider,
        baseUrl: res.data.baseUrl,
        apiKey: '',
        defaultModel: res.data.defaultModel ?? '',
        timeoutMs: res.data.timeoutMs,
        supportsVision: res.data.supportsVision,
        reasoningEffort: res.data.reasoningEffort ?? '',
      };
      form.setFieldsValue(initial);
      setFormValues(initial);
      lastProviderRef.current = res.data.provider;

      if (res.data.defaultModel) {
        setModelOptions([{ value: res.data.defaultModel, label: res.data.defaultModel }]);
      }
    } catch (err: unknown) {
      setError(extractErrorMessage(err, '加载配置失败'));
    } finally {
      setLoading(false);
    }
  }, [form]);

  // ── Refresh config (light) — only updates the config info display,
  //     does NOT touch form values. Used after test/fetch-models. ──

  const refreshConfig = useCallback(async () => {
    try {
      const res = await api.get<ApiResponse<AiConfigData>>('/ai/config');
      setConfig(res.data);
    } catch {
      // silent — config display refresh is non-critical
    }
  }, []);

  useEffect(() => {
    loadConfig();
  }, [loadConfig]);

  // ── Provider change → swap baseUrl ──

  const handleProviderChange = useCallback(
    (provider: AiProvider) => {
      const result = shouldAutoSwapBaseUrl(provider, formValues.baseUrl, lastProviderRef.current);
      if (result.shouldSwap) {
        form.setFieldValue('baseUrl', result.baseUrl);
      }
      lastProviderRef.current = provider;
    },
    [form, formValues.baseUrl],
  );

  const currentProvider = formValues.provider;
  const isFixedProvider = FIXED_PROVIDERS.includes(currentProvider);

  // ── Fetch models from provider ──

  const handleFetchModels = useCallback(async () => {
    setFetchingModels(true);
    try {
      await form.validateFields(['provider', 'baseUrl']);

      const { provider, baseUrl, apiKey: formKey } = formValues;
      const body: Record<string, unknown> = { provider };
      if (baseUrl) body.baseUrl = baseUrl;
      if (formKey && formKey !== '••••') body.apiKey = formKey;

      const res = await api.post<FetchModelsResult>('/ai/config/models', body);
      if (res.success && res.models.length > 0) {
        const options = res.models.map((m) => ({ value: m.id, label: m.id }));
        setModelOptions(options);
        message.success(`获取到 ${res.models.length} 个模型`);
      } else {
        message.warning(res.message || '未获取到可用模型');
      }
    } catch (err: unknown) {
      message.error(extractErrorMessage(err, '获取模型列表失败'));
    } finally {
      setFetchingModels(false);
    }
  }, [form, formValues]);

  // ── Save ──

  const handleSave = useCallback(async () => {
    try {
      // Validate fields (for UI error display) — actual values come from state
      await form.validateFields(['provider', 'baseUrl', 'timeoutMs']);

      const { provider, baseUrl, defaultModel, apiKey, timeoutMs, supportsVision, reasoningEffort } =
        formValues;

      if (provider === 'OPENAI_COMPATIBLE' && !baseUrl) {
        message.error('OPENAI_COMPATIBLE 模式必须填写 Base URL');
        return;
      }

      setSaving(true);

      const resolvedBaseUrl = baseUrl || PROVIDER_DEFAULTS[provider] || '';

      const body: Record<string, unknown> = {
        provider,
        baseUrl: resolvedBaseUrl,
        defaultModel: defaultModel || undefined,
        enabled: true,
        supportsVision,
        timeoutMs,
        reasoningEffort: reasoningEffort || null,
      };

      if (apiKey && apiKey !== '••••') {
        body.apiKey = apiKey;
      }

      await api.put('/ai/config', body);
      message.success('配置已保存');
      form.setFieldValue('apiKey', '');
      setFormValues((prev) => ({ ...prev, apiKey: '' }));
    } catch (err: unknown) {
      message.error(extractErrorMessage(err, '保存失败'));
      setSaving(false);
      return;
    }

    try {
      await loadConfig();
    } catch (err: unknown) {
      message.warning(extractErrorMessage(err, '配置已保存，但刷新失败'));
    } finally {
      setSaving(false);
    }
  }, [formValues, form, loadConfig]);

  // ── Test connection ──

  const handleTest = useCallback(async () => {
    try {
      const fieldsToValidate = ['provider', 'timeoutMs'] as string[];
      if (currentProvider === 'OPENAI_COMPATIBLE') {
        fieldsToValidate.push('baseUrl');
      }
      await form.validateFields(fieldsToValidate);

      setTesting(true);
      setTestResult(null);

      const { provider, baseUrl, defaultModel, apiKey, timeoutMs, reasoningEffort } = formValues;
      const body: Record<string, unknown> = { provider, timeoutMs };
      if (baseUrl) body.baseUrl = baseUrl;
      if (defaultModel) body.defaultModel = defaultModel;
      if (apiKey && apiKey !== '••••') body.apiKey = apiKey;
      if (reasoningEffort) body.reasoningEffort = reasoningEffort;

      const res = await api.post<TestResult>('/ai/config/test', body);
      setTestResult(res);
      await refreshConfig();
    } catch (err: unknown) {
      setTestResult({
        success: false,
        latencyMs: null,
        modelCount: null,
        modelAvailable: false,
        testedAt: new Date().toISOString(),
        message: extractErrorMessage(err, '测试请求失败'),
      });
    } finally {
      setTesting(false);
    }
  }, [formValues, form, loadConfig, currentProvider]);

  // ── Clear key ──

  const handleClearKey = useCallback(() => {
    const isEnv = config?.keySource === 'environment';
    modal.confirm({
      title: '确认清除密钥',
      content: isEnv
        ? '数据库中的密钥将被清除，但环境变量 AI_API_KEY 仍可使用。确定继续？'
        : '密钥将被永久清除，之后将无法使用 AI 功能。确定继续？',
      okText: '确认清除',
      okType: 'danger',
      cancelText: '取消',
      onOk: async () => {
        try {
          await api.post('/ai/config/clear-key');
          message.success('密钥已清除');
          await loadConfig();
        } catch (err: unknown) {
          message.error(extractErrorMessage(err, '清除失败'));
        }
      },
    });
  }, [config, loadConfig, modal]);

  // ── Step navigation ──

  const goNext = useCallback(async () => {
    // Validate current step fields before moving
    try {
      if (currentStep === 0) {
        await form.validateFields(['provider', 'baseUrl', 'timeoutMs']);
      } else if (currentStep === 1) {
        // API key step — optional, no validation needed
      } else if (currentStep === 2) {
        await form.validateFields(['defaultModel']);
      }
      setCurrentStep((s) => Math.min(s + 1, STEP_ITEMS.length - 1));
    } catch {
      // Validation failed — form will show errors
    }
  }, [currentStep, form]);

  const goPrev = useCallback(() => {
    setCurrentStep((s) => Math.max(s - 1, 0));
  }, []);

  // ── No read permission ──

  if (!canRead) {
    return (
      <div className={styles.container}>
        <Alert type="error" title="您没有查看 AI 配置的权限" showIcon />
      </div>
    );
  }

  if (loading) {
    return (
      <div className={styles.container} style={{ textAlign: 'center', paddingTop: 80 }}>
        <Spin size="large" />
      </div>
    );
  }

  if (error && !config) {
    return (
      <div className={styles.container}>
        <Alert type="error" title={error} showIcon />
      </div>
    );
  }

  // ── Render step content ──

  const renderStepContent = () => {
    switch (currentStep) {
      // Step 0: Provider + Base URL + Timeout
      case 0:
        return (
          <Card
            title={<span className={styles.cardTitle}>服务商配置</span>}
            extra={<CloudServerOutlined />}
          >
            <Form.Item
              name="provider"
              label="Provider"
              rules={[{ required: true, message: '请选择 Provider' }]}
              preserve
            >
              <Select
                options={PROVIDER_OPTIONS}
                onChange={handleProviderChange}
                disabled={!canWrite}
                size="large"
              />
            </Form.Item>

            <Form.Item
              name="baseUrl"
              label="Base URL"
              rules={[
                { required: true, message: '请输入 Base URL' },
                { type: 'url', message: '请输入合法的 URL' },
              ]}
              preserve
            >
              <Input
                placeholder={
                  config?.provider
                    ? PROVIDER_DEFAULTS[config.provider]
                    : 'https://api.deepseek.com'
                }
                disabled={!canWrite || (isFixedProvider && canWrite)}
                size="large"
              />
            </Form.Item>

            <Form.Item
              name="timeoutMs"
              label="请求超时 (毫秒)"
              rules={[
                { required: true, message: '请输入超时时间' },
                { type: 'number', min: 1000, max: 120000, message: '范围: 1000-120000' },
              ]}
              preserve
            >
              <InputNumber
                min={1000}
                max={120000}
                step={1000}
                style={{ width: '100%' }}
                disabled={!canWrite}
                size="large"
              />
            </Form.Item>
          </Card>
        );

      // Step 1: API Key
      case 1:
        return (
          <Card
            title={<span className={styles.cardTitle}>密钥配置</span>}
            extra={<SafetyOutlined />}
          >
            <Form.Item name="apiKey" label="API Key" preserve>
              <Input.Password
                placeholder={config?.hasApiKey ? '已安全保存，留空则保持不变' : '请输入 API Key'}
                disabled={!canWrite}
                autoComplete="new-password"
                size="large"
              />
            </Form.Item>

            {config && (
              <Descriptions column={1} size="small" style={{ marginBottom: 12 }}>
                <Descriptions.Item label="状态">
                  {config.hasApiKey ? (
                    <Tag color="green">{config.maskedApiKey || '••••'}</Tag>
                  ) : (
                    <Tag color="default">未配置</Tag>
                  )}
                </Descriptions.Item>
                <Descriptions.Item label="来源">
                  <Tag color={sourceColor(config.keySource)}>{sourceLabel(config.keySource)}</Tag>
                  {config.keySource === 'environment' && (
                    <span style={{ marginLeft: 8, fontSize: 12, color: '#999' }}>
                      由环境变量托管，需在服务器修改
                    </span>
                  )}
                </Descriptions.Item>
                <Descriptions.Item label="最后更新">
                  {formatDateTime(config.updatedAt)}
                </Descriptions.Item>
              </Descriptions>
            )}

            {config?.hasDatabaseKey && canWrite && (
              <div style={{ marginBottom: 8 }}>
                <Button danger size="small" onClick={handleClearKey}>
                  清除服务器保存密钥
                </Button>
              </div>
            )}

            {config?.keySource === 'environment' && !config.hasDatabaseKey && (
              <div style={{ marginBottom: 8, fontSize: 12, color: '#999' }}>
                密钥由环境变量提供，无法通过页面清除
              </div>
            )}

            <div className={styles.safetyNote}>
              API Key 使用 AES-256-GCM 加密存储，每次保存使用随机 IV。传输层通过 HTTPS
              保护，服务端日志不记录密钥。
            </div>
            <div className={styles.safetyNoteKey}>
              也可通过环境变量 <Typography.Text code>AI_API_KEY</Typography.Text> 注入密钥，
              环境变量优先级高于数据库存储。
            </div>
          </Card>
        );

      // Step 2: Model selection
      case 2:
        return (
          <Card
            title={<span className={styles.cardTitle}>模型选择</span>}
            extra={<RobotOutlined />}
          >
            <div className={styles.modelFetchRow}>
              <Button
                icon={<ReloadOutlined />}
                onClick={handleFetchModels}
                loading={fetchingModels}
                disabled={!canWrite}
              >
                获取模型列表
              </Button>
              {modelOptions.length > 0 && (
                <Tag color="blue">{modelOptions.length} 个可用模型</Tag>
              )}
            </div>

            <Form.Item
              name="defaultModel"
              label="默认模型"
              rules={[{ required: true, message: '请选择或输入默认模型' }]}
              style={{ marginTop: 16 }}
              preserve
            >
              <AutoComplete
                options={modelOptions}
                placeholder="选择或输入模型名称，如 deepseek-chat, gpt-4"
                disabled={!canWrite}
                size="large"
                filterOption={(inputValue, option) =>
                  option?.value?.toLowerCase().includes(inputValue.toLowerCase()) ?? false
                }
              />
            </Form.Item>

            <Form.Item
              name="supportsVision"
              label="图片理解"
              valuePropName="checked"
              extra="仅当所选模型确实支持图片输入时开启；关闭时 AI 助手会阻止发送图片。"
              preserve
            >
              <Switch disabled={!canWrite} checkedChildren="已启用" unCheckedChildren="未启用" />
            </Form.Item>

            <Form.Item
              name="reasoningEffort"
              label="推理强度 (reasoning_effort)"
              extra="OpenAI o 系列等支持该参数的模型生效；DeepSeek 官方接口不支持，选择后也不会发送。"
              preserve
            >
              <Select
                disabled={!canWrite}
                size="large"
                options={[
                  { value: '', label: '不设置（跟随模型默认）' },
                  { value: 'low', label: '低 (low)' },
                  { value: 'medium', label: '中 (medium)' },
                  { value: 'high', label: '高 (high)' },
                  { value: 'xhigh', label: '极高 (xhigh)' },
                ]}
              />
            </Form.Item>

            {config?.verified && (
              <div style={{ marginTop: 8 }}>
                <Tag icon={<CheckCircleOutlined />} color="success">
                  上次验证通过
                </Tag>
                {config.lastTestLatencyMs != null && (
                  <span style={{ marginLeft: 8, fontSize: 12, color: '#999' }}>
                    延迟: {config.lastTestLatencyMs}ms
                  </span>
                )}
              </div>
            )}
          </Card>
        );

      // Step 3: Save & Test
      case 3:
        return (
          <Card
            title={<span className={styles.cardTitle}>保存并测试</span>}
            extra={<CheckCircleOutlined />}
          >
            <Alert
              type="info"
              message="配置预览"
              description={
                <Descriptions column={1} size="small" style={{ marginTop: 8 }}>
                  <Descriptions.Item label="服务商">
                    <Tag color="blue">
                      {PROVIDER_OPTIONS.find((o) => o.value === currentProvider)?.label ??
                        currentProvider ??
                        '-'}
                    </Tag>
                  </Descriptions.Item>
                  <Descriptions.Item label="Base URL">
                    <Typography.Text code>
                      {formValues.baseUrl || '-'}
                    </Typography.Text>
                  </Descriptions.Item>
                  <Descriptions.Item label="默认模型">
                    <Tag>{formValues.defaultModel || '未设置'}</Tag>
                  </Descriptions.Item>
                  <Descriptions.Item label="密钥">
                    {(() => {
                      const hasFormKey = formValues.apiKey && formValues.apiKey !== '••••';
                      if (config?.hasApiKey) {
                        return <Tag color="green">{config.maskedApiKey || '••••'}</Tag>;
                      }
                      if (hasFormKey) {
                        return <Tag color="blue">已填写（未保存）</Tag>;
                      }
                      return <Tag color="red">未配置</Tag>;
                    })()}
                  </Descriptions.Item>
                  <Descriptions.Item label="超时">
                    {formValues.timeoutMs}ms
                  </Descriptions.Item>
                  <Descriptions.Item label="图片理解">
                    <Tag color={formValues.supportsVision ? 'blue' : 'default'}>
                      {formValues.supportsVision ? '已启用' : '未启用'}
                    </Tag>
                  </Descriptions.Item>
                  <Descriptions.Item label="状态">
                    <Tag color={config?.enabled ? 'green' : 'default'}>
                      {config?.enabled ? '已启用' : '未启用'}
                    </Tag>
                  </Descriptions.Item>
                </Descriptions>
              }
              style={{ marginBottom: 16 }}
            />

            <Space>
              {canWrite && (
                <Button type="primary" icon={<SaveOutlined />} onClick={handleSave} loading={saving} size="large">
                  保存配置
                </Button>
              )}
              {canTest && (
                <Button icon={<ApiOutlined />} onClick={handleTest} loading={testing} size="large">
                  测试连接
                </Button>
              )}
            </Space>

            {/* Test result */}
            {testResult && (
              <Card size="small" className={styles.testResult}>
                <Descriptions column={{ xs: 1, sm: 2 }} size="small">
                  <Descriptions.Item label="结果">
                    {testResult.success ? (
                      testResult.modelAvailable ? (
                        <Tag icon={<CheckCircleOutlined />} color="success">
                          成功
                        </Tag>
                      ) : (
                        <Tag icon={<WarningOutlined />} color="warning">
                          模型未找到
                        </Tag>
                      )
                    ) : (
                      <Tag icon={<CloseCircleOutlined />} color="error">
                        失败
                      </Tag>
                    )}
                  </Descriptions.Item>
                  <Descriptions.Item label="延迟">
                    {testResult.latencyMs != null ? `${testResult.latencyMs} ms` : '-'}
                  </Descriptions.Item>
                  <Descriptions.Item label="模型数量">
                    {testResult.modelCount != null ? testResult.modelCount : '-'}
                  </Descriptions.Item>
                  <Descriptions.Item label="测试时间">
                    {formatDateTime(testResult.testedAt)}
                  </Descriptions.Item>
                </Descriptions>
                <Alert
                  type={
                    testResult.success
                      ? testResult.modelAvailable
                        ? 'success'
                        : 'warning'
                      : 'error'
                  }
                  title={testResult.message}
                  style={{ marginTop: 8 }}
                />
              </Card>
            )}
          </Card>
        );

      default:
        return null;
    }
  };

  // ── Render ──

  return (
    <div className={styles.container}>
      <div className={styles.header}>
        <h2>AI 模型配置</h2>
        <p className={styles.headerDesc}>密钥仅保存在服务器端，浏览器无法读取明文</p>
        <div className={styles.statusRow}>
          <Space size="small">
            <Tag color={config?.enabled ? 'green' : 'default'}>
              {config?.enabled ? '已启用' : '未启用'}
            </Tag>
            {config?.verified && <Tag color="blue">已验证</Tag>}
            {config?.hasApiKey && (
              <Tag color={sourceColor(config?.keySource || 'none')}>
                密钥: {sourceLabel(config?.keySource || 'none')}
              </Tag>
            )}
          </Space>
        </div>
      </div>

      <Steps
        current={currentStep}
        items={STEP_ITEMS}
        onChange={setCurrentStep}
        className={styles.steps}
        size="small"
      />

      <Form
        form={form}
        layout="vertical"
        initialValues={{ timeoutMs: 30000 }}
        onValuesChange={handleFormChange}
      >
        <div className={styles.stepContent}>{renderStepContent()}</div>

        <div className={styles.stepNav}>
          <Button onClick={goPrev} disabled={currentStep === 0} icon={<span>←</span>}>
            上一步
          </Button>
          {currentStep < STEP_ITEMS.length - 1 ? (
            <Button type="primary" onClick={goNext} icon={<span>→</span>}>
              下一步
            </Button>
          ) : null}
        </div>
      </Form>
    </div>
  );
};

export default AiConfigPage;
