import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
  DownloadOutlined,
  InboxOutlined,
  PlusOutlined,
  UploadOutlined,
} from '@ant-design/icons';
import { ProTable } from '@ant-design/pro-components';
import type { ActionType } from '@ant-design/pro-components';
import { App as AntdApp, Button, Modal, Upload } from 'antd';
import type { UploadFile } from 'antd';
import { createUserColumns } from './columns';
import UserFormDrawer from './components/UserFormDrawer';
import type { UserFormMode } from './components/UserFormDrawer';
import {
  deleteEmployee,
  exportEmployees,
  getEmployeeList,
  getOrgTree,
  getRoleOptions,
  importEmployees,
} from './server';
import type {
  EmployeeListQuery,
  EmployeeVO,
  OrgTreeNode,
  SelectOption,
  TenantEmployeeListRequest,
} from './types';
import './Users.scss';

const flattenOrgOptions = (nodes: OrgTreeNode[]): SelectOption[] =>
  nodes.flatMap((node) => [
    { label: node.orgName, value: node.id },
    ...flattenOrgOptions(node.children ?? []),
  ]);

const Users = () => {
  const actionRef = useRef<ActionType>();
  const lastQueryRef = useRef<TenantEmployeeListRequest>({});
  const { message, modal } = AntdApp.useApp();
  const [orgOptions, setOrgOptions] = useState<SelectOption[]>([]);
  const [roleOptions, setRoleOptions] = useState<SelectOption[]>([]);
  const [formOpen, setFormOpen] = useState(false);
  const [formMode, setFormMode] = useState<UserFormMode>('create');
  const [activeEmployee, setActiveEmployee] = useState<EmployeeVO | null>(null);
  const [importOpen, setImportOpen] = useState(false);
  const [importFileList, setImportFileList] = useState<UploadFile[]>([]);
  const [importing, setImporting] = useState(false);
  const [exporting, setExporting] = useState(false);

  useEffect(() => {
    let active = true;

    const loadOptions = async () => {
      try {
        const [orgs, roles] = await Promise.all([getOrgTree(), getRoleOptions()]);
        if (!active) return;

        setOrgOptions(flattenOrgOptions(orgs));
        setRoleOptions(roles.map((role) => ({ label: role.roleName, value: role.id })));
      } catch {
        // 错误已由 request 统一提示
      }
    };

    void loadOptions();

    return () => {
      active = false;
    };
  }, []);

  const orgNameMap = useMemo(
    () => new Map(orgOptions.map((option) => [option.value, option.label])),
    [orgOptions],
  );

  const roleNameMap = useMemo(
    () => new Map(roleOptions.map((option) => [option.value, option.label])),
    [roleOptions],
  );

  const openCreate = useCallback(() => {
    setActiveEmployee(null);
    setFormMode('create');
    setFormOpen(true);
  }, []);

  const closeForm = useCallback(() => {
    setFormOpen(false);
    setActiveEmployee(null);
  }, []);

  const handleFormSuccess = useCallback(() => {
    closeForm();
    actionRef.current?.reload();
  }, [closeForm]);

  const openEdit = useCallback((record: EmployeeVO) => {
    setActiveEmployee(record);
    setFormMode('edit');
    setFormOpen(true);
  }, []);

  const openDetail = useCallback((record: EmployeeVO) => {
    setActiveEmployee(record);
    setFormMode('detail');
    setFormOpen(true);
  }, []);

  const handleDelete = useCallback(
    (record: EmployeeVO) => {
      modal.confirm({
        title: '删除员工',
        content: `确定要删除员工「${record.name}」吗？删除后不可恢复。`,
        okText: '删除',
        cancelText: '取消',
        okButtonProps: { danger: true },
        onOk: async () => {
          await deleteEmployee({ id: record.id });
          message.success('员工已删除');
          actionRef.current?.reload();
        },
      });
    },
    [message, modal],
  );

  const handleExport = useCallback(async () => {
    setExporting(true);
    try {
      const blob = await exportEmployees({ orgId: lastQueryRef.current.orgId });
      const url = URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = url;
      link.download = 'employees.xlsx';
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.setTimeout(() => URL.revokeObjectURL(url), 0);
      message.success('导出成功');
    } catch {
      // 错误已由 request 统一提示
    } finally {
      setExporting(false);
    }
  }, [message]);

  const handleImport = useCallback(async () => {
    const file = importFileList[0]?.originFileObj;
    if (!file) {
      message.warning('请先选择要导入的 Excel 文件');
      return;
    }

    setImporting(true);
    try {
      const count = await importEmployees({ file });
      message.success(`成功导入 ${count} 条员工`);
      setImportOpen(false);
      setImportFileList([]);
      actionRef.current?.reload();
    } catch {
      // 错误已由 request 统一提示
    } finally {
      setImporting(false);
    }
  }, [importFileList, message]);

  const columns = useMemo(
    () =>
      createUserColumns({
        orgOptions,
        roleOptions,
        orgNameMap,
        roleNameMap,
        onDetail: openDetail,
        onEdit: openEdit,
        onDelete: handleDelete,
      }),
    [orgOptions, roleOptions, orgNameMap, roleNameMap, openDetail, openEdit, handleDelete],
  );

  return (
    <div className="users-page">
      <ProTable<EmployeeVO, EmployeeListQuery>
        rowKey="id"
        actionRef={actionRef}
        columns={columns}
        cardProps={{ className: 'table-card' }}
        search={{ labelWidth: 'auto', defaultCollapsed: false }}
        scroll={{ x: 1290 }}
        options={false}
        pagination={{
          defaultPageSize: 10,
          showSizeChanger: true,
          hideOnSinglePage: false,
          showTotal: (total) => `共 ${total} 条`,
        }}
        toolBarRender={() => [
          <Button
            key="import"
            icon={<UploadOutlined />}
            onClick={() => {
              setImportFileList([]);
              setImportOpen(true);
            }}
          >
            导入
          </Button>,
          <Button
            key="export"
            icon={<DownloadOutlined />}
            loading={exporting}
            onClick={handleExport}
          >
            导出
          </Button>,
          <Button key="create" type="primary" icon={<PlusOutlined />} onClick={openCreate}>
            新增员工
          </Button>,
        ]}
        request={async (params) => {
          const query: TenantEmployeeListRequest = {
            page: params.current,
            size: params.pageSize,
            keyword: params.keyword?.trim() || undefined,
            status: params.status,
            orgId: params.orgId,
            roleId: params.roleId,
          };
          lastQueryRef.current = query;

          const result = await getEmployeeList(query);

          return {
            data: result.records ?? [],
            total: result.total ?? 0,
            success: true,
          };
        }}
      />

      <UserFormDrawer
        open={formOpen}
        mode={formMode}
        record={activeEmployee}
        orgOptions={orgOptions}
        roleOptions={roleOptions}
        onClose={closeForm}
        onSuccess={handleFormSuccess}
      />

      <Modal
        title="导入员工"
        open={importOpen}
        onOk={handleImport}
        onCancel={() => {
          setImportOpen(false);
          setImportFileList([]);
        }}
        confirmLoading={importing}
        okText="导入"
        cancelText="取消"
      >
        <Upload.Dragger
          accept=".xlsx,.xls"
          maxCount={1}
          fileList={importFileList}
          beforeUpload={() => false}
          onChange={({ fileList }) => setImportFileList(fileList)}
        >
          <p className="ant-upload-drag-icon">
            <InboxOutlined />
          </p>
          <p className="ant-upload-text">点击或拖拽 Excel 文件到此处</p>
          <p className="ant-upload-hint">仅支持 .xlsx / .xls 格式</p>
        </Upload.Dragger>
      </Modal>
    </div>
  );
};

export default Users;
