import React, { useEffect, useState, useMemo } from 'react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useApiMutation } from '../../hooks/useApiMutation';
import { validateResponse } from '../../utils/validate';
import { integrationConfigSchema } from '../../api/schemas';
import {
  Alert,
  Button,
  Card,
  Descriptions,
  Divider,
  Form,
  Input,
  Space,
  Spin,
  Tag,
} from 'antd';
import {
  ApiOutlined,
  CheckCircleOutlined,
  CloseCircleOutlined,
  SaveOutlined,
} from '@ant-design/icons';
import api from '../../api';
import { message } from '../../ui/app-message';
import { usePermission } from '../../hooks/usePermission';
import PermissionButton from '../../components/PermissionButton';
import {
  buildDingTalkConfigPayload,
  isAppSecretRequired,
  type DingTalkConfigFormValues,
} from './integration-config-form';
import {
  cacheDingTalkDraft,
  cacheDingTalkServerSnapshot,
  commitDingTalkConfig,
  readDingTalkConfigCache,
} from './integration-config-cache';
import { IntegrationOrgSyncPanel } from './IntegrationOrgSyncPanel';

interface DingTalkConfig {
  agentId: string;
  corpId: string;
}

const IntegrationConfigPage: React.FC = () => {
  const initialCache = useMemo(() => readDingTalkConfigCache(), []);
  const { hasPermission, hasAllPermissions } = usePermission();
  const canCreateClass = hasPermission('class:create');
  const [saving, setSaving] = useState(false);
  const [testing, setTesting] = useState(false);
  const [form] = Form.useForm<DingTalkConfigFormValues>();
  const queryClient = useQueryClient();

  const {
    data: serverConfig = { config: initialCache.config, verified: initialCache.verified },
    isLoading: configLoading,
    isFetching: configFetching,
  } = useQuery<{ config: DingTalkConfig | null; verified: boolean | null }>({
    queryKey: ['integration', 'config'],
    queryFn: async () => {
      try {
        const res = await api.get<{
          success: boolean;
          data: Array<{ type: string; verify: boolean; config: DingTalkConfig }>;
        }>('/integration/config');
        const validated = validateResponse<{
          success: boolean;
          data: Array<{ type: string; verify: boolean; config: DingTalkConfig }>;
        }>(integrationConfigSchema, res);
        const dt = validated.data?.find((c) => c.type === 'DINGTALK');
        return { config: dt?.config ?? null, verified: dt ? dt.verify : null };
      } catch {
        // not configured
        return { config: initialCache.config, verified: initialCache.verified };
      }
    },
  });
  const config = serverConfig.config;
  const verified = serverConfig.verified;
  const loading = !initialCache.loaded && (configLoading || configFetching);

  const saveMutation = useApiMutation(
    async (payload: Record<string, unknown>) =>
      api.post('/integration/config', { type: 'DINGTALK', config: payload }),
    { invalidate: [['integration', 'config']] },
  );

  // 初始表单值来自本地缓存（外部存储同步）
  useEffect(() => {
    form.setFieldsValue(initialCache.formValues);
  }, [form, initialCache]);

  // 服务端配置同步进 localStorage 缓存，并回填表单
  useEffect(() => {
    cacheDingTalkServerSnapshot(config, verified);
    if (config) form.setFieldsValue(readDingTalkConfigCache().formValues);
  }, [config, verified, form]);

  const handleSave = async () => {
    const values = await form.validateFields();
    const payload = buildDingTalkConfigPayload(values);
    setSaving(true);
    try {
      await saveMutation.mutateAsync(payload);
      message.success('配置已保存');
      commitDingTalkConfig({ corpId: payload.corpId, agentId: payload.agentId });
      form.setFieldValue('appSecret', undefined);
    } catch {
      // 错误提示由 useApiMutation 统一处理
    } finally {
      setSaving(false);
    }
  };

  const handleTest = async () => {
    const values = await form.validateFields();
    const payload = buildDingTalkConfigPayload(values);
    setTesting(true);
    try {
      const res = await api.post<{ success: boolean; message: string }>(
        '/integration/config/test',
        {
          type: 'DINGTALK',
          config: payload,
        },
      );
      queryClient.setQueryData(['integration', 'config'], (prev) => ({
        ...(prev ?? { config: initialCache.config, verified: initialCache.verified }),
        verified: res.success,
      }));
      message.success(res.message);
    } catch (e: unknown) {
      const err = e as { message?: string };
      queryClient.setQueryData(['integration', 'config'], (prev) => ({
        ...(prev ?? { config: initialCache.config, verified: initialCache.verified }),
        verified: false,
      }));
      message.error(err?.message || '连接失败');
    } finally {
      setTesting(false);
    }
  };

  return (
    <Card
      title="钉钉集成配置"
      extra={
        <Space>
          {verified === true && (
            <Tag icon={<CheckCircleOutlined />} color="success">
              已连接
            </Tag>
          )}
          {verified === false && (
            <Tag icon={<CloseCircleOutlined />} color="error">
              未连接
            </Tag>
          )}
        </Space>
      }
    >
      <Spin spinning={loading}>
        {config && (
          <Descriptions size="small" column={2} style={{ marginBottom: 24 }}>
            <Descriptions.Item label="CorpId">{config.corpId || '-'}</Descriptions.Item>
            <Descriptions.Item label="AppKey">{config.agentId || '-'}</Descriptions.Item>
            <Descriptions.Item label="同步方式">手动触发</Descriptions.Item>
          </Descriptions>
        )}

        <Alert
          type="info"
          message="配置钉钉应用凭证后，可在本页手动获取组织架构并导入用户。排班同步仍在排课管理中手动触发。"
          style={{ marginBottom: 24 }}
          showIcon
        />

        <Form
          form={form}
          layout="vertical"
          initialValues={initialCache.formValues}
          onValuesChange={(_changed, values) => cacheDingTalkDraft(values)}
          style={{ maxWidth: 520 }}
        >
          <Form.Item
            name="corpId"
            label="CorpId（企业ID）"
            rules={[{ required: true, message: '请输入 CorpId' }]}
          >
            <Input placeholder="dingxxxxxxxx" />
          </Form.Item>
          <Form.Item
            name="agentId"
            label="AppKey（应用凭证）"
            rules={[{ required: true, message: '请输入 AppKey' }]}
          >
            <Input placeholder="从钉钉开放平台获取" />
          </Form.Item>
          <Form.Item
            name="appSecret"
            label="AppSecret（应用密钥）"
            rules={[
              {
                required: isAppSecretRequired(!!config),
                message: '首次配置请输入 AppSecret',
              },
            ]}
            extra={
              config
                ? '已保存密钥；留空保持原值，输入新值将替换原密钥'
                : '首次配置需要填写完整 AppSecret'
            }
          >
            <Input.Password placeholder={config ? '留空保持已保存的密钥' : '从钉钉开放平台获取'} />
          </Form.Item>
          <Space>
            <PermissionButton
              permission="integration:trigger"
              type="primary"
              icon={<SaveOutlined />}
              loading={saving}
              onClick={handleSave}
            >
              保存配置
            </PermissionButton>
            <Button icon={<ApiOutlined />} loading={testing} onClick={handleTest}>
              测试连接
            </Button>
          </Space>
        </Form>

        {config && hasAllPermissions('sync:read', 'class:view', 'class:edit') && (
          <>
            <Divider titlePlacement="start">组织用户导入</Divider>
            <IntegrationOrgSyncPanel canCreateClass={canCreateClass} />
          </>
        )}
      </Spin>
    </Card>
  );
};

export default IntegrationConfigPage;
