import React, { useEffect, useState, useMemo, useCallback } from 'react';
import {
  Card, Form, Input, Button, Space, Spin, Alert, Descriptions, Tag, Divider,
  Drawer, Tree, Select, TreeSelect, Modal, DatePicker,
  Row, Col, List,
} from 'antd';
import {
  SaveOutlined, ApiOutlined, CheckCircleOutlined, CloseCircleOutlined,
  SyncOutlined, BankOutlined, UserOutlined,
  DeleteOutlined,
} from '@ant-design/icons';
import type { DataNode } from 'antd/es/tree';
import type { TreeSelectProps } from 'antd/es/tree-select';
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';

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

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

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

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

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

type DeptPickerTreeNode = NonNullable<TreeSelectProps<number>['treeData']>[number];

interface ClassItem {
  id: number;
  name: string;
  code: string;
  classType?: string;
  startDate?: string;
  endDate?: string;
  notes?: string;
}

interface ImportResult {
  imported: number;
  skipped: number;
}

interface DingTalkAttendanceGroup {
  group_id: number;
  group_name: string;
  type: string;
  member_count: number;
}

interface AttendanceGroupResponse {
  success: boolean;
  data: DingTalkAttendanceGroup[];
}

interface DeleteAttendanceGroupsResponse {
  success: boolean;
  data: {
    total: number;
    deleted: Array<{ groupId: number; groupName: string }>;
    failed: Array<{ groupId: number; groupName: string; error: string }>;
  };
}


const IntegrationConfigPage: React.FC = () => {
  const { hasAllPermissions } = usePermission();
  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<DingTalkConfigFormValues>();

  // ── Manual organization sync ──
  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 [deptPickerTree, setDeptPickerTree] = useState<DeptPickerTreeNode[]>([]);
  const [checkedKeys, setCheckedKeys] = useState<React.Key[]>([]);
  const [selectedClassId, setSelectedClassId] = useState<number | null>(null);
  const [classes, setClasses] = useState<ClassItem[]>([]);
  const [classForm] = Form.useForm();
  const [classModalOpen, setClassModalOpen] = useState(false);
  const [attendanceGroups, setAttendanceGroups] = useState<DingTalkAttendanceGroup[]>([]);
  const [deleteGroupsOpen, setDeleteGroupsOpen] = useState(false);
  const [loadingGroups, setLoadingGroups] = useState(false);
  const [deletingGroups, setDeletingGroups] = 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 fetchConfig();
  }, []);

  const handleSave = async () => {
    const values = await form.validateFields();
    const payload = buildDingTalkConfigPayload(values);
    setSaving(true);
    try {
      await api.post('/integration/config', { type: 'DINGTALK', config: payload });
      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();
    const payload = buildDingTalkConfigPayload(values);
    setTesting(true);
    try {
      const res = await api.post<{ success: boolean; message: string }>('/integration/config/test', {
        type: 'DINGTALK',
        config: payload,
      });
      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 loadDeptTree = async () => {
    try {
      const res = await api.get<OrgTreeResponse>('/sync/dingtalk/org-tree');
      if (res.success && res.data) {
        const toTreeNode = (nodes: OrgTreeNodeRaw[]): DeptPickerTreeNode[] =>
          nodes.map((n) => ({
            title: n.name,
            value: n.id,
            children: n.children ? toTreeNode(n.children) : undefined,
          }));
        setDeptPickerTree(toTreeNode(res.data));
      }
    } catch {
      message.error('获取部门架构失败');
    }
  };

  const fetchClasses = async () => {
    try {
      const res = await api.get<ClassItem[] | { data: ClassItem[] }>('/classes');
      if (Array.isArray(res)) {
        setClasses(res);
      } else {
        setClasses(res.data ?? []);
      }
    } catch { /* ignore */ }
  };

  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);
        setCheckedKeys([]);
        setSelectedClassId(null);
        setDrawerOpen(true);
        fetchClasses();
      } else {
        message.error('获取组织架构失败');
      }
    } catch (e: unknown) {
      const err = e as { message?: string };
      message.error(err?.message || '获取组织架构失败');
    } finally {
      setFetchingTree(false);
    }
  };


  const buildTreeData = useCallback((nodes: DingOrgTreeNodeExt[]): DataNode[] => {
    return nodes.map((node) => {
      const users = node.users ?? [];
      const children: DataNode[] = [
        ...buildTreeData(node.children ?? []),
        ...users.map((u) => ({
          title: (
            <Space>
              <UserOutlined />
              <span>{u.name}</span>
              {u.mobile ? <Tag>{u.mobile}</Tag> : null}
            </Space>
          ),
          key: `user-${u.userid}`,
          isLeaf: true,
        })),
      ];
      return {
        title: (
          <Space size="small">
            <BankOutlined />
            <span>{node.name}</span>
            <Tag>{users.length}人</Tag>
          </Space>
        ),
        key: `dept-${node.id}`,
        // Only attach children when there are any, so empty/leaf departments
        // don't render a phantom expand arrow that opens to nothing.
        ...(children.length > 0 ? { children } : {}),
      };
    });
  }, []);

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

  const extractCheckedUsers = useCallback((): Array<{ dingUserId: string; name: string; mobile?: string }> => {
    const result: Array<{ dingUserId: string; name: string; mobile?: string }> = [];
    const walk = (nodes: DingOrgTreeNodeExt[]) => {
      for (const node of nodes) {
        for (const u of node.users ?? []) {
          if (checkedKeys.includes(`user-${u.userid}`)) {
            result.push({ dingUserId: u.userid, name: u.name, mobile: u.mobile || undefined });
          }
        }
        walk(node.children ?? []);
      }
    };
    walk(orgTree);
    return result;
  }, [checkedKeys, orgTree]);

  const handleJoinClass = async () => {
    if (selectedClassId === null) return message.warning('请先选择一个班级');
    const users = extractCheckedUsers();
    if (users.length === 0) return message.warning('请勾选要导入的用户');

    setImporting(true);
    try {
      const res = await api.post<ImportResult>(`/classes/${selectedClassId}/students/import`, { users });
      message.success(`导入 ${res.imported} 人，跳过 ${res.skipped} 人`);
      setCheckedKeys([]);
      setSelectedClassId(null);
    } catch (e: unknown) {
      const err = e as { message?: string };
      message.error(err?.message || '导入失败');
    } finally {
      setImporting(false);
    }
  };

  const handleCreateClass = async () => {
    try {
      const values = await classForm.validateFields();
      const users = extractCheckedUsers();
      await api.post('/classes', { ...values, users });
      message.success('班级创建成功');
      setClassModalOpen(false);
      classForm.resetFields();
      setCheckedKeys([]);
      fetchClasses();
    } catch (e: unknown) {
      const err = e as { message?: string };
      message.error(err?.message || '创建失败');
    } finally {
      setImporting(false);
    }
  };

  const openDeleteAllGroups = async () => {
    setLoadingGroups(true);
    try {
      const response = await api.get<AttendanceGroupResponse>('/sync/dingtalk/attendance-groups');
      setAttendanceGroups(response.data);
      setDeleteGroupsOpen(true);
    } catch (error: unknown) {
      message.error(error instanceof Error ? error.message : '获取钉钉考勤组失败');
    } finally {
      setLoadingGroups(false);
    }
  };

  const deleteAllGroups = async () => {
    setDeletingGroups(true);
    try {
      const response = await api.post<DeleteAttendanceGroupsResponse>(
        '/sync/dingtalk/attendance-groups/delete-all',
      );
      setDeleteGroupsOpen(false);
      setAttendanceGroups([]);
      if (response.data.failed.length > 0) {
        message.warning(
          `已删除 ${response.data.deleted.length} 个，失败 ${response.data.failed.length} 个`,
        );
      } else {
        message.success(`已删除钉钉全部 ${response.data.deleted.length} 个考勤组`);
      }
    } catch (error: unknown) {
      message.error(error instanceof Error ? error.message : '删除钉钉考勤组失败');
    } finally {
      setDeletingGroups(false);
    }
  };

  const syncPanel = config && hasAllPermissions('sync:read', 'class:view', 'class:edit')
    ? (
            <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>
                <PermissionButton
                  permission="sync:trigger"
                  danger
                  icon={<DeleteOutlined />}
                  loading={loadingGroups}
                  onClick={openDeleteAllGroups}
                >
                  删除钉钉全部考勤组
                </PermissionButton>
              </Space>

              {drawerOpen && (
                <Drawer
                  title="钉钉组织架构 — 批量导入"
                  open={drawerOpen}
                  onClose={() => { setDrawerOpen(false); }}
                  width={900}
                  footer={
                    <Space>
                      <Button onClick={() => { setDrawerOpen(false); }}>取消</Button>
                      <Button
                        type="primary"
                        loading={importing}
                        disabled={checkedKeys.filter((k) => String(k).startsWith('user-')).length === 0 || selectedClassId === null}
                        onClick={handleJoinClass}
                      >加入选中的班级</Button>
                      <Button
                        disabled={checkedKeys.filter((k) => String(k).startsWith('user-')).length === 0}
                        onClick={() => setClassModalOpen(true)}
                      >创建班级</Button>
                    </Space>
                  }
                >
                  <Row gutter={16}>
                    <Col span={14}>
                      <div style={{ maxHeight: '60vh', overflow: 'auto' }}>
                        <Tree
                          checkable
                          treeData={treeData}
                          defaultExpandAll
                          showLine={{ showLeafIcon: false }}
                          checkedKeys={checkedKeys}
                          onCheck={(checked) => setCheckedKeys(checked as React.Key[])}
                        />
                      </div>
                    </Col>
                    <Col span={10}>
                      <Card title="班级列表" size="small"
                        extra={<Button size="small" onClick={() => setClassModalOpen(true)}>+ 创建班级</Button>}>
                        <List
                          dataSource={classes}
                          renderItem={(cls: ClassItem) => (
                            <List.Item
                              onClick={() => setSelectedClassId(cls.id)}
                              style={{
                                cursor: 'pointer',
                                background: selectedClassId === cls.id ? '#e6f4ff' : undefined,
                                borderRadius: 4,
                                padding: '8px 12px',
                              }}
                            >
                              <List.Item.Meta title={cls.name} description={`${cls.code}  ${cls.classType || ''}`} />
                            </List.Item>
                          )}
                        />
                      </Card>
                    </Col>
                  </Row>

                  { /* Create class Modal */ }
                  <Modal
                    title="创建班级"
                    open={classModalOpen}
                    onOk={handleCreateClass}
                    onCancel={() => { setClassModalOpen(false); classForm.resetFields(); }}
                    confirmLoading={importing}
                    destroyOnClose
                  >
                    <Form form={classForm} layout="vertical">
                      <Form.Item name="name" label="班级名称" rules={[{ required: true }]}>
                        <Input />
                      </Form.Item>
                      <Form.Item name="code" label="班级编码" rules={[{ required: true }]}>
                        <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="notes" label="备注">
                        <Input.TextArea rows={2} />
                      </Form.Item>
                    </Form>
                  </Modal>
                </Drawer>
              )}
              <Modal
                title="确认删除钉钉全部考勤组"
                open={deleteGroupsOpen}
                okText="确认全部删除"
                okButtonProps={{ danger: true, disabled: attendanceGroups.length === 0 }}
                cancelText="取消"
                confirmLoading={deletingGroups}
                onOk={deleteAllGroups}
                onCancel={() => setDeleteGroupsOpen(false)}
              >
                <Alert
                  type="error"
                  showIcon
                  message={`将永久删除钉钉上的 ${attendanceGroups.length} 个考勤组`}
                  description="本地班级和排课不会删除。删除后需在排课管理中重新同步，才能重建考勤组。"
                  style={{ marginBottom: 12 }}
                />
                <List
                  size="small"
                  bordered
                  dataSource={attendanceGroups}
                  style={{ maxHeight: 280, overflow: 'auto' }}
                  renderItem={(group) => (
                    <List.Item>
                      <List.Item.Meta
                        title={group.group_name}
                        description={`ID ${group.group_id} · ${group.member_count} 人`}
                      />
                    </List.Item>
                  )}
                />
              </Modal>
            </div>
    )
    : null;

  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" 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>

        {syncPanel && (
          <>
            <Divider titlePlacement="start">组织用户导入</Divider>
            {syncPanel}
          </>
        )}
      </Spin>
    </Card>
  );
};

export default IntegrationConfigPage;
