import React, { useEffect, useState, useMemo, useCallback } from 'react';
import {
  Card, Form, Input, Button, Space, message, Spin, Switch, Alert, Descriptions, Tag,
  Tabs, Drawer, Tree, Checkbox, Select, TreeSelect, Modal, DatePicker, InputNumber, Table, Popconfirm,
} from 'antd';
import {
  SaveOutlined, ApiOutlined, CheckCircleOutlined, CloseCircleOutlined,
  SyncOutlined, ReloadOutlined, PlusOutlined,
} from '@ant-design/icons';
import type { DataNode } from 'antd/es/tree';
import api from '../../api';

interface DingTalkConfig {
  agentId: string;
  appSecret: string;
  corpId: string;
  startEnable: boolean;
}

interface DingOrgTreeNodeExt {
  id: number;
  name: string;
  parentId: number;
  children: DingOrgTreeNodeExt[];
  users: Array<{ userid: string; name: string; mobile: string; deptIds: number[] }>;
}

interface RoleItem {
  id: number;
  name: string;
  status: number;
}

interface OrgTreeNodeRaw {
  id: number;
  name: string;
  children?: OrgTreeNodeRaw[];
}

interface OrgTreeResponse {
  success: boolean;
  data: OrgTreeNodeRaw[];
}

interface OrgTreeWithUsersResponse {
  success: boolean;
  data: DingOrgTreeNodeExt[];
}

interface ImportUsersResponse {
  success: boolean;
  data: {
    teacherCount: number;
    studentCount: number;
    classCount: number;
    skipped: number;
    warnings: string[];
  };
}

interface ClassMarkForm {
  deptId: number;
  name: string;
  code: string;
  classType: string;
  startDate?: string;
  endDate?: string;
  maxStudents?: number;
  notes?: string;
}

const UserTreeNode: React.FC<{
  u: { userid: string; name: string; mobile: string };
  isTeacher: boolean;
  onToggle: () => void;
  roleId: number | undefined;
  defaultRoleId: number | null;
  roles: Array<{ id: number; name: string }>;
  onRoleChange: (roleId: number) => void;
}> = React.memo(({ u, isTeacher, onToggle, roleId, defaultRoleId, roles, onRoleChange }) => (
  <Space size="small">
    <Checkbox checked={isTeacher} onChange={onToggle}>老师</Checkbox>
    <span style={{ fontWeight: 500 }}>{u.name}</span>
    {u.mobile && <Tag style={{ marginLeft: 4 }}>{u.mobile}</Tag>}
    {isTeacher && (
      <Select
        size="small"
        style={{ width: 100, marginLeft: 8 }}
        value={roleId || defaultRoleId}
        onChange={onRoleChange}
        options={roles.map((r) => ({ label: r.name, value: r.id }))}
        placeholder="选择角色"
        onClick={(e: React.MouseEvent) => e.stopPropagation()}
      />
    )}
  </Space>
));

const IntegrationConfigPage: React.FC = () => {
  const [loading, setLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [testing, setTesting] = useState(false);
  const [config, setConfig] = useState<DingTalkConfig | null>(null);
  const [verified, setVerified] = useState<boolean | null>(null);
  const [form] = Form.useForm<DingTalkConfig>();

  // ── Sync Users Tab ──
  const [syncRootDeptId, setSyncRootDeptId] = useState<number | undefined>(undefined);
  const [orgTree, setOrgTree] = useState<DingOrgTreeNodeExt[]>([]);
  const [drawerOpen, setDrawerOpen] = useState(false);
  const [fetchingTree, setFetchingTree] = useState(false);
  const [importing, setImporting] = useState(false);
  const [teacherChecks, setTeacherChecks] = useState<Record<string, boolean>>({});
  const [teacherRoles, setTeacherRoles] = useState<Record<string, number>>({});
  const [roles, setRoles] = useState<Array<{ id: number; name: string }>>([]);
  const [defaultTeacherRoleId, setDefaultTeacherRoleId] = useState<number | null>(null);
  const [deptPickerTree, setDeptPickerTree] = useState<Array<{ title: string; value: number; children?: Array<{ title: string; value: number; children?: unknown[] }> }>>([]);
  const [classMarks, setClassMarks] = useState<Record<number, ClassMarkForm>>({});
  const [classModalOpen, setClassModalOpen] = useState(false);
  const [classModalDept, setClassModalDept] = useState<{ id: number; name: string } | null>(null);
  const [classForm] = Form.useForm<ClassMarkForm>();

  // ── DingTalk Bindings Tab ──
  const [bindings, setBindings] = useState<Array<{ id: number; userId: number; dingUserId: string; dingName: string | null; dingMobile: string | null; user: { id: number; username: string; name: string } }>>([]);
  const [unboundUsers, setUnboundUsers] = useState<Array<{ id: number; username: string; name: string }>>([]);
  const [bindModalOpen, setBindModalOpen] = useState(false);
  const [bindForm] = Form.useForm<{ userId: number; dingUserId: string; dingName?: string; dingMobile?: string }>();
  const [bindSubmitting, setBindSubmitting] = useState(false);

  const fetchConfig = async () => {
    setLoading(true);
    try {
      const res = await api.get<{ success: boolean; data: Array<{ type: string; verify: boolean; config: DingTalkConfig }> }>('/integration/config');
      const dt = res.data?.find((c) => c.type === 'DINGTALK');
      if (dt) {
        setConfig(dt.config);
        setVerified(dt.verify);
        form.setFieldsValue(dt.config);
      }
    } catch {
      // not configured
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    void Promise.all([fetchConfig(), fetchRoles()]);
  }, []);

  const handleSave = async () => {
    const values = await form.validateFields();
    setSaving(true);
    try {
      await api.post('/integration/config', { type: 'DINGTALK', config: values });
      message.success('配置已保存');
      await fetchConfig();
    } catch (e: unknown) {
      const err = e as { message?: string };
      message.error(err?.message || '保存失败');
    } finally {
      setSaving(false);
    }
  };

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

  const fetchRoles = async () => {
    try {
      const res = await api.get<RoleItem[]>('/rbac/roles');
      const activeRoles = res.filter((r) => r.status !== 0);
      setRoles(activeRoles);
      const teacherRole = activeRoles.find((r) => r.name === '班主任');
      setDefaultTeacherRoleId(teacherRole?.id || activeRoles[0]?.id || null);
    } catch {
      message.error('获取角色列表失败');
    }
  };

  const fetchBindings = useCallback(async () => {
    try {
      const res = await api.get<typeof bindings>('/rbac/user-ding-mappings');
      setBindings(res);
    } catch { /* ignore */ }
  }, []);

  const fetchUnboundUsers = useCallback(async () => {
    try {
      const res = await api.get<typeof unboundUsers>('/rbac/user-ding-mappings/unbound-users');
      setUnboundUsers(res);
    } catch { /* ignore */ }
  }, []);

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

  const handleBindSubmit = async () => {
    try {
      const values = await bindForm.validateFields();
      setBindSubmitting(true);
      await api.post('/rbac/user-ding-mappings', values);
      message.success('绑定成功');
      setBindModalOpen(false);
      bindForm.resetFields();
      fetchBindings();
    } catch (e: unknown) {
      const err = e as { message?: string };
      if (err.message) message.error(err.message);
    } finally {
      setBindSubmitting(false);
    }
  };

  const handleUnbind = async (id: number) => {
    Modal.confirm({
      title: '确认解绑？',
      content: '解绑后该用户将无法自动匹配钉钉考勤。',
      okText: '解绑',
      okType: 'danger',
      onOk: async () => {
        await api.delete(`/rbac/user-ding-mappings/${id}`);
        message.success('已解绑');
        fetchBindings();
      },
    });
  };

  const loadDeptTree = async () => {
    try {
      const res = await api.get<OrgTreeResponse>('/sync/dingtalk/org-tree');
      if (res.success && res.data) {
        const toTreeNode = (nodes: OrgTreeNodeRaw[]): Array<{ title: string; value: number; children?: Array<{ title: string; value: number; children?: unknown[] }> }> =>
          nodes.map((n) => ({
            title: n.name,
            value: n.id,
            children: n.children ? toTreeNode(n.children) : undefined,
          }));
        setDeptPickerTree(toTreeNode(res.data));
      }
    } catch {
      message.error('获取部门架构失败');
    }
  };

  const handleFetchOrgTree = async () => {
    setFetchingTree(true);
    try {
      const params: Record<string, string> = {};
      if (syncRootDeptId) params.rootDeptId = String(syncRootDeptId);
      const res = await api.get<OrgTreeWithUsersResponse>('/sync/dingtalk/org-tree-with-users', { params });
      if (res.success && res.data) {
        setOrgTree(res.data);
        setTeacherChecks({});
        setTeacherRoles({});
        setDrawerOpen(true);
      } else {
        message.error('获取组织架构失败');
      }
    } catch (e: unknown) {
      const err = e as { message?: string };
      message.error(err?.message || '获取组织架构失败');
    } finally {
      setFetchingTree(false);
    }
  };

  const openClassModal = (deptId: number, deptName: string) => {
    const existing = classMarks[deptId];
    if (existing) {
      classForm.setFieldsValue(existing);
    } else {
      classForm.setFieldsValue({
        deptId,
        name: deptName,
        code: '',
        classType: 'culture',
      });
    }
    setClassModalDept({ id: deptId, name: deptName });
    setClassModalOpen(true);
  };

  const handleClassModalOk = async () => {
    const values = await classForm.validateFields();
    setClassMarks((prev) => ({
      ...prev,
      [values.deptId]: values,
    }));
    setClassModalOpen(false);
    setClassModalDept(null);
  };

  const handleClassModalCancel = () => {
    setClassModalOpen(false);
    setClassModalDept(null);
  };

  const handleImportUsers = async () => {
    setImporting(true);
    try {
      const allUsers: Array<{
        dingUserId: string;
        name: string;
        mobile: string;
        deptIds: number[];
      }> = [];

      const flatten = (nodes: DingOrgTreeNodeExt[]) => {
        for (const node of nodes) {
          allUsers.push(
            ...node.users.map((u) => ({
              dingUserId: u.userid,
              name: u.name,
              mobile: u.mobile,
              deptIds: u.deptIds || [],
            })),
          );
          flatten(node.children);
        }
      };
      flatten(orgTree);

      const payload = {
        classes: Object.values(classMarks),
        users: allUsers.map((u) => ({
          dingUserId: u.dingUserId,
          name: u.name,
          mobile: u.mobile,
          roleId: teacherChecks[u.dingUserId]
            ? (teacherRoles[u.dingUserId] || defaultTeacherRoleId)
            : null,
          dingDeptIds: u.deptIds,
        })),

      const res = await api.post('/sync/dingtalk/import-users', payload) as ImportUsersResponse;
      const data = res.data;
      message.success(
        `导入完成：${data.teacherCount} 位老师，${data.studentCount} 位学生` +
        (data.classCount ? `，${data.classCount} 个班级` : '') +
        (data.skipped > 0 ? `，${data.skipped} 已跳过` : ''),
      );
      if (data.warnings?.length > 0) {
        message.warning(data.warnings.join('；'), 8);
      }
      setDrawerOpen(false);
    } catch (e: unknown) {
      const err = e as { message?: string };
      message.error(err?.message || '导入失败');
    } finally {
      setImporting(false);
    }
  };

  const buildTreeData = useCallback((nodes: DingOrgTreeNodeExt[]): DataNode[] => {
    return nodes.map((node) => ({
      title: (
        <Space size="small">
          <span>{node.name}</span>
          {node.children.length === 0 && node.users.length > 0 && (
            <>
              {classMarks[node.id] ? (
                <Tag
                  color="blue"
                  style={{ cursor: 'pointer' }}
                  onClick={() => openClassModal(node.id, node.name)}
                >
                  班级: {classMarks[node.id].name} [已标记]
                </Tag>
              ) : (
                <Button
                  size="small"
                  type="link"
                  icon={<span>🏫</span>}
                  onClick={() => openClassModal(node.id, node.name)}
                >
                  标为班级
                </Button>
              )}
            </>
          )}
        </Space>
      ),
      key: `dept-${node.id}`,
      children: [
        ...buildTreeData(node.children),
        ...node.users.map((u) => ({
          title: (
            <UserTreeNode
              key={u.userid}
              u={{ userid: u.userid, name: u.name, mobile: u.mobile }}
              isTeacher={!!teacherChecks[u.userid]}
              onToggle={() => {
                setTeacherChecks((prev) => ({
                  ...prev,
                  [u.userid]: !prev[u.userid],
                }));
                if (teacherChecks[u.userid]) {
                  setTeacherRoles((prev) => {
                    const next = { ...prev };
                    delete next[u.userid];
                    return next;
                  });
                }
              }}
              roleId={teacherRoles[u.userid]}
              defaultRoleId={defaultTeacherRoleId}
              roles={roles}
              onRoleChange={(roleId) =>
                setTeacherRoles((prev) => ({ ...prev, [u.userid]: roleId }))
              }
            />
          ),
          key: `user-${u.userid}`,
          selectable: false,
        })),
      ],
    }));
  }, [classMarks, teacherChecks, teacherRoles, defaultTeacherRoleId, roles]);

  const treeData = useMemo(() => buildTreeData(orgTree), [orgTree, buildTreeData]);

  const syncTabItems = config
    ? [
        {
          key: 'sync-users',
          label: '同步用户',
          children: (
            <div>
              <Alert
                type="info"
                message="从钉钉获取组织架构，勾选老师并分配角色，其余用户将作为学生导入。"
                style={{ marginBottom: 16 }}
                showIcon
              />
              <Space>
                <TreeSelect
                  treeData={deptPickerTree}
                  value={syncRootDeptId}
                  onChange={(v) => setSyncRootDeptId(v)}
                  placeholder="选择起始部门（不选=全部）"
                  allowClear
                  treeDefaultExpandAll
                  style={{ minWidth: 240 }}
                  onDropdownVisibleChange={(open) => { if (open) loadDeptTree(); }}
                />
                <Button
                  type="primary"
                  icon={<SyncOutlined />}
                  loading={fetchingTree}
                  onClick={handleFetchOrgTree}
                >
                  获取组织架构
                </Button>
              </Space>
              <Modal
                title={classMarks[classModalDept?.id ?? -1] ? '修改班级信息' : '标记为班级'}
                open={classModalOpen}
                onOk={handleClassModalOk}
                onCancel={handleClassModalCancel}
                destroyOnClose
              >
                <Form form={classForm} layout="vertical">
                  <Form.Item name="deptId" hidden><Input /></Form.Item>
                  <Form.Item name="name" label="班级名称" rules={[{ required: true, message: '请输入班级名称' }]}>
                    <Input />
                  </Form.Item>
                  <Form.Item name="code" label="班级编码" rules={[{ required: true, message: '请输入班级编码' }]}>
                    <Input placeholder="如 CS2024-01" />
                  </Form.Item>
                  <Form.Item name="classType" label="班型" rules={[{ required: true }]}>
                    <Select
                      options={[
                        { value: 'culture', label: '文化课' },
                        { value: 'professional', label: '专业课' },
                        { value: 'bootcamp', label: '集训营' },
                        { value: 'sprint', label: '冲刺班' },
                      ]}
                    />
                  </Form.Item>
                  <Form.Item name="startDate" label="开班日期">
                    <DatePicker style={{ width: '100%' }} />
                  </Form.Item>
                  <Form.Item name="endDate" label="结束日期">
                    <DatePicker style={{ width: '100%' }} />
                  </Form.Item>
                  <Form.Item name="maxStudents" label="最大人数">
                    <InputNumber min={0} style={{ width: '100%' }} placeholder="0 表示不限制" />
                  </Form.Item>
                  <Form.Item name="notes" label="备注">
                    <Input.TextArea rows={2} />
                  </Form.Item>
                </Form>
              </Modal>

              {drawerOpen && (
                <Drawer
                  title="钉钉组织架构 — 勾选老师"
                  open={drawerOpen}
                  onClose={() => { setDrawerOpen(false); setClassMarks({}); }}
                  width={520}
                  footer={
                    <Space>
                      <Button onClick={() => { setDrawerOpen(false); setClassMarks({}); }}>取消</Button>
                      <Button
                        type="primary"
                        icon={<ReloadOutlined />}
                        loading={importing}
                        disabled={!defaultTeacherRoleId}
                        title={!defaultTeacherRoleId ? '角色列表未加载，无法导入' : undefined}
                        onClick={handleImportUsers}
                      >
                        导入
                      </Button>
                    </Space>
                  }
                >
                  {treeData.length > 0 ? (
                    <Tree
                      treeData={treeData}
                      defaultExpandAll
                      blockNode
                      showLine={{ showLeafIcon: false }}
                    />
                  ) : (
                    <Spin />
                  )}
                </Drawer>
              )}
            </div>
          ),
        },
      ]
    : [];

  const tabItems = [
    {
      key: 'config',
      label: '配置',
      children: (
        <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="启用同步">
                <Tag color={config.startEnable ? 'green' : 'default'}>
                  {config.startEnable ? '已启用' : '未启用'}
                </Tag>
              </Descriptions.Item>
            </Descriptions>
          )}

          <Alert
            type="info"
            message="配置钉钉应用凭证后，可使用组织架构同步、考勤导入和排班同步功能。"
            style={{ marginBottom: 24 }}
            showIcon
          />

          <Form form={form} layout="vertical" style={{ maxWidth: 480 }}>
            <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: true, message: '请输入 AppSecret' }]}
              extra="保存后仅返回脱敏信息，重新编辑时需再次输入完整密钥"
            >
              <Input.Password placeholder="从钉钉开放平台获取" />
            </Form.Item>
            <Form.Item name="startEnable" label="启用同步" valuePropName="checked">
              <Switch />
            </Form.Item>
            <Space>
              <Button type="primary" icon={<SaveOutlined />} loading={saving} onClick={handleSave}>
                保存配置
              </Button>
              <Button icon={<ApiOutlined />} loading={testing} onClick={handleTest}>
                测试连接
              </Button>
            </Space>
          </Form>
        </Spin>
      ),
    },
    {
      key: 'bindings',
      label: '钉钉绑定',
      children: (
        <div>
          <div style={{ marginBottom: 16, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <span style={{ fontWeight: 500 }}>用户绑定管理</span>
            <Button
              type="primary"
              icon={<PlusOutlined />}
              onClick={async () => {
                await fetchUnboundUsers();
                setBindModalOpen(true);
              }}
            >
              新增绑定
            </Button>
          </div>
          <Table
            dataSource={bindings}
            rowKey="id"
            columns={[
              {
                title: '本地用户',
                key: 'user',
                render: (_: unknown, r: typeof bindings[number]) => (
                  <Space>
                    <span>{r.user?.name || '-'}</span>
                    <Tag>{r.user?.username}</Tag>
                  </Space>
                ),
              },
              { title: '钉钉用户ID', dataIndex: 'dingUserId', key: 'dingUserId' },
              { title: '钉钉名称', dataIndex: 'dingName', key: 'dingName', render: (v: string | null) => v || '-' },
              { title: '钉钉手机', dataIndex: 'dingMobile', key: 'dingMobile', render: (v: string | null) => v || '-' },
              {
                title: '操作',
                key: 'actions',
                render: (_: unknown, r: typeof bindings[number]) => (
                  <Popconfirm title="确认解绑？" onConfirm={() => handleUnbind(r.id)} okText="解绑" okType="danger">
                    <Button size="small" danger>解绑</Button>
                  </Popconfirm>
                ),
              },
            ]}
            pagination={{ pageSize: 20 }}
            locale={{ emptyText: '暂无绑定记录' }}
          />
          <Modal
            title="新增钉钉绑定"
            open={bindModalOpen}
            onOk={handleBindSubmit}
            onCancel={() => { setBindModalOpen(false); bindForm.resetFields(); }}
            confirmLoading={bindSubmitting}
          >
            <Form form={bindForm} layout="vertical">
              <Form.Item name="userId" label="本地用户" rules={[{ required: true, message: '请选择用户' }]}>
                <Select
                  showSearch
                  placeholder="搜索本地用户"
                  optionFilterProp="label"
                  options={unboundUsers.map((u) => ({
                    value: u.id,
                    label: `${u.name || u.username} (${u.username})`,
                  }))}
                />
              </Form.Item>
              <Form.Item name="dingUserId" label="钉钉用户ID" rules={[{ required: true, message: '请输入钉钉用户ID' }]} extra="在钉钉管理后台 → 通讯录 → 成员详情 中可查看">
                <Input placeholder="如: manager123" />
              </Form.Item>
            </Form>
          </Modal>
        </div>
      ),
    },
    ...syncTabItems,
  ];

  return (
    <Card title="钉钉集成配置" extra={
      <Space>
        {verified === true && <Tag icon={<CheckCircleOutlined />} color="success">已连接</Tag>}
        {verified === false && <Tag icon={<CloseCircleOutlined />} color="error">未连接</Tag>}
      </Space>
    }>
      <Tabs items={tabItems} />
    </Card>
  );
};

export default IntegrationConfigPage;
