import React, { useState, useCallback, useMemo } from 'react';
import {
  Alert,
  Button,
  Card,
  Col,
  DatePicker,
  Drawer,
  Form,
  Input,
  List,
  Modal,
  Row,
  Select,
  Space,
  Tag,
  Tree,
  TreeSelect,
} from 'antd';
import type { DataNode } from 'antd/es/tree';
import type { TreeSelectProps } from 'antd/es/tree-select';
import {
  BankOutlined,
  StopOutlined,
  SyncOutlined,
  UserOutlined,
} from '@ant-design/icons';
import api from '../../api';
import { message } from '../../ui/app-message';
import PermissionButton from '../../components/PermissionButton';
import { getErrorMessage } from '../../utils/error';

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;
  conflicts: 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 }>;
  };
}

interface IntegrationOrgSyncPanelProps {
  canCreateClass: boolean;
}

export const IntegrationOrgSyncPanel: React.FC<IntegrationOrgSyncPanelProps> = ({
  canCreateClass,
}) => {
  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 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 (e) {
      console.error('获取部门架构失败', e);
      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) {
      message.error(getErrorMessage(e, '获取组织架构失败'));
    } 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,
      });
      if (res.conflicts > 0) {
        message.warning(
          `导入 ${res.imported} 人，跳过 ${res.skipped} 人，${res.conflicts} 人需人工绑定`,
        );
      } else {
        message.success(`导入 ${res.imported} 人，跳过 ${res.skipped} 人`);
      }
      setCheckedKeys([]);
      setSelectedClassId(null);
    } catch (e: unknown) {
      message.error(getErrorMessage(e, '导入失败'));
    } 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) {
      message.error(getErrorMessage(e, '创建失败'));
    } 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);
    }
  };

  return (
    <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={<StopOutlined />}
          loading={loadingGroups}
          onClick={openDeleteAllGroups}
        >
          清空钉钉全部考勤组
        </PermissionButton>
      </Space>

      {drawerOpen && (
        <Drawer
          title="钉钉组织架构 — 批量导入"
          open={drawerOpen}
          onClose={() => setDrawerOpen(false)}
          size="min(900px, 100vw)"
          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>
              {canCreateClass ? (
                <Button
                  disabled={checkedKeys.filter((k) => String(k).startsWith('user-')).length === 0}
                  onClick={() => setClassModalOpen(true)}
                >
                  创建班级
                </Button>
              ) : null}
            </Space>
          }
        >
          <Row gutter={[16, 16]}>
            <Col xs={24} md={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 xs={24} md={10}>
              <Card
                title="班级列表"
                size="small"
                extra={
                  canCreateClass ? (
                    <Button size="small" onClick={() => setClassModalOpen(true)}>
                      + 创建班级
                    </Button>
                  ) : null
                }
              >
                <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>

          {canCreateClass ? (
            <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>
          ) : null}
        </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
          title={`将永久清空钉钉上的 ${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>
  );
};
