import React, { useEffect, useState, useCallback, useRef } from 'react';
import { useQuery } from '@tanstack/react-query';
import { useApiMutation } from '../../hooks/useApiMutation';
import { validateResponse } from '../../utils/validate';
import { aiConfigEnvelopeSchema } from '../../api/schemas';
import { App, Alert, Button, Form, Space, Spin, Steps, Tag } from 'antd';
import api from '../../api';
import { message } from '../../ui/app-message';
import { usePermission } from '../../hooks/usePermission';
import type { AiProvider } from './helpers';
import {
  PROVIDER_DEFAULTS,
  FIXED_PROVIDERS,
  sourceLabel,
  sourceColor,
  shouldAutoSwapBaseUrl,
} from './helpers';
import { getErrorMessage } from '../../utils/error';
import {
  ProviderStep,
  KeyStep,
  ModelStep,
  SaveTestStep,
} from './AiConfigSteps';
import type { AiConfigData, FormValues, TestResult } from './AiConfigSteps';
import styles from './index.module.css';

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

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

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

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

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

  const [currentStep, setCurrentStep] = useState(0);
  const [saving, setSaving] = useState(false);
  const [testing, setTesting] = useState(false);
  const [fetchingModels, setFetchingModels] = useState(false);
  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 skipNextSyncRef = useRef(false);
  const appliedConfigRef = useRef<AiConfigData | null>(null);

  const {
    data: config,
    isLoading: configLoading,
    isFetching: configFetching,
    refetch: refetchConfig,
  } = useQuery<AiConfigData | null>({
    queryKey: ['ai', 'config'],
    queryFn: async () => {
      try {
        const res = await api.get<ApiResponse<AiConfigData>>('/ai/config');
        return validateResponse<ApiResponse<AiConfigData>>(aiConfigEnvelopeSchema, res).data;
      } catch (err: unknown) {
        setError(getErrorMessage(err, '加载配置失败'));
        return null;
      }
    },
  });
  const loading = configLoading || configFetching;
  const refreshConfig = useCallback(() => {
    skipNextSyncRef.current = true;
    return refetchConfig();
  }, [refetchConfig]);
  const saveMutation = useApiMutation(
    async (body: Record<string, unknown>) => api.put('/ai/config', body),
    { invalidate: [['ai', 'config']] },
  );
  const clearKeyMutation = useApiMutation(
    async () => api.post('/ai/config/clear-key'),
    { invalidate: [['ai', 'config']] },
  );

  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 }));
    },
    [],
  );

  // 配置数据到位后同步进表单（antd Form 属于外部系统）；
  // refreshConfig（测试/拉模型后）只刷新展示，不覆盖用户表单输入。
  useEffect(() => {
    if (!config) return;
    if (skipNextSyncRef.current) {
      skipNextSyncRef.current = false;
      appliedConfigRef.current = config;
      return;
    }
    if (appliedConfigRef.current === config) return;
    appliedConfigRef.current = config;
    const initial: FormValues = {
      provider: config.provider,
      baseUrl: config.baseUrl,
      apiKey: '',
      defaultModel: config.defaultModel ?? '',
      timeoutMs: config.timeoutMs,
      supportsVision: config.supportsVision,
      reasoningEffort: config.reasoningEffort ?? '',
    };
    form.setFieldsValue(initial);
    setFormValues(initial);
    lastProviderRef.current = config.provider;
    if (config.defaultModel) {
      setModelOptions([{ value: config.defaultModel, label: config.defaultModel }]);
    }
    setError(null);
  }, [config, form]);

  // ── 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(getErrorMessage(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 saveMutation.mutateAsync(body);
      message.success('配置已保存');
      form.setFieldValue('apiKey', '');
      setFormValues((prev) => ({ ...prev, apiKey: '' }));
    } catch {
      // 错误提示由 useApiMutation 统一处理
    } finally {
      setSaving(false);
    }
  }, [formValues, form, saveMutation]);

  // ── 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: getErrorMessage(err, '测试请求失败'),
      });
    } finally {
      setTesting(false);
    }
  }, [formValues, form, currentProvider, refreshConfig]);

  // ── 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 clearKeyMutation.mutateAsync();
          message.success('密钥已清除');
        } catch {
          // 错误提示由 useApiMutation 统一处理
        }
      },
    });
  }, [config, modal, clearKeyMutation]);

  // ── Step navigation ──

  const goNext = useCallback(async () => {
    try {
      if (currentStep === 0) {
        await form.validateFields(['provider', 'baseUrl', 'timeoutMs']);
      } 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>
    );
  }

  const renderStepContent = () => {
    switch (currentStep) {
      case 0:
        return (
          <ProviderStep
            canWrite={canWrite}
            isFixedProvider={isFixedProvider}
            config={config}
            onProviderChange={handleProviderChange}
          />
        );
      case 1:
        return <KeyStep canWrite={canWrite} config={config} onClearKey={handleClearKey} />;
      case 2:
        return (
          <ModelStep
            canWrite={canWrite}
            config={config}
            onFetchModels={handleFetchModels}
            fetchingModels={fetchingModels}
            modelOptions={modelOptions}
          />
        );
      case 3:
        return (
          <SaveTestStep
            canWrite={canWrite}
            canTest={canTest}
            config={config}
            currentProvider={currentProvider}
            formValues={formValues}
            onSave={handleSave}
            saving={saving}
            onTest={handleTest}
            testing={testing}
            testResult={testResult}
          />
        );
      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;
