import React, { CSSProperties, useEffect, useMemo, useState } from 'react';
import { queryUserListByRoleID, queryLeader } from '@/services/boom';
import { connect } from 'umi';
import {
  CheckOutlined,
  PlusOutlined,
  PlusSquareOutlined,
} from '@ant-design/icons';
import {
  Popover,
  Radio,
  RadioChangeEvent,
  Space,
  Spin,
  Steps,
  Timeline,
  Checkbox,
} from 'antd';
import { useModel, useRequest } from '@umijs/max';
import { CheckboxValueType } from 'antd/es/checkbox/Group';

const { Step } = Steps;

const TYPE = {
  ROLE: 'role',
  USER: 'user',
  LEADER: 'leader',
} as const;

interface AuditNode {
  is_cc: 0 | 1;
  seq: number;
  type: (typeof TYPE)[keyof typeof TYPE];
  value: number[];
  checkValue: [];
  label: string;
}

const ApprovalProcess = (props: any) => {
  const {
    approvalProcess,
    leaderData = [],
    dispatch,
    onChange,
    roleList = [],
  } = props;
  const { userList, run } = useModel('userList');
  const [checkValue, setCheckValue] = useState<number[][]>([]);

  const { auditList, ccList } = useMemo<{
    auditList: AuditNode[];
    ccList: AuditNode[];
  }>(() => {
    let auditList: AuditNode[] = [],
      ccList: AuditNode[] = [];
    approvalProcess.forEach((item: any, index: number) => {
      if (!item) return;
      let node: AuditNode = {
        is_cc: item[0].is_cc,
        type: item[0].type,
        checkValue: [],
        seq: index,
        label: item[0].label,
        value: item.map((node: any) => node.value),
      };

      if (node.is_cc == 1) {
        ccList.push(node);
      } else {
        auditList.push(node);
      }
    });
    return { auditList, ccList };
  }, [approvalProcess]);

  const onCheckValue = (value: number[], index: number) => {
    let values = [...checkValue];
    values[index] = value;
    setCheckValue(values);
    onChange(values);
  };

  useEffect(() => {
    dispatch({
      type: 'user/getRoleList',
    });
    run();
  }, []);
  const rowStyle: CSSProperties = {
    display: 'flex',
    flexDirection: 'column',
    fontSize: 16,
  };

  const renderAudits = (list: AuditNode[]) => {
    return list.map((item: AuditNode, index: number) => {
      return {
        children: (
          <AuditNodeStep
            key={`${item.type}-${item.value.join('.')}-${index}`}
            leaderData={leaderData}
            item={item}
            roleList={roleList}
            userList={userList}
            value={checkValue[item.seq]}
            onChange={(value: number[]) => onCheckValue(value, item.seq)}
          />
        ),
      };
    });
  };

  return (
    <div>
      <Timeline items={renderAudits(auditList)}></Timeline>

      {ccList.length > 0 && <Timeline items={renderAudits(ccList)}></Timeline>}
    </div>
  );
};

interface AuditNodeStepProps {
  item: AuditNode;
  leaderData: any;
  roleList: any;
  userList: any;
  value: number[];
  onChange: (value: number[]) => void;
}

const AuditNodeStep = (props: AuditNodeStepProps) => {
  const {
    item,
    leaderData,
    roleList = [],
    userList = [],
    value,
    onChange,
  } = props;

  const [selectUserList, setSelectUserList] = useState([]);
  const [loading, setLoading] = useState(false);

  const getLeaderContent = (length: any) => (
    <Steps
      progressDot
      current={-1}
      direction="vertical"
      items={leaderData
        ?.slice(0, length || 0)
        .map((leader: any) => ({ title: leader.CName }))}
    ></Steps>
  );

  const handleOpen = async () => {
    setLoading(true);
    if (item.type !== 'role') return;
    const data = await queryUserListByRoleID({ role_id: item.value[0] });
    setSelectUserList(data);
    setLoading(false);
  };

  const selectedUserId = (list: CheckboxValueType[]) => {
    onChange(list as number[]);
  };

  const content = (
    <Spin spinning={loading}>
      <Checkbox.Group
        style={{ display: 'block' }}
        onChange={selectedUserId}
        value={value as any}
      >
        {selectUserList
          .filter((item: any) => item.c_name)
          .map((item: any) => (
            <Checkbox
              style={{ whiteSpace: 'nowrap' }}
              key={item.user_id}
              value={Number(item.user_id)}
            >
              {item.c_name}
            </Checkbox>
          ))}
      </Checkbox.Group>
    </Spin>
  );

  if (item.type == TYPE.LEADER) {
    return (
      <div style={{ marginBottom: 20 }}>
        <Popover
          placement="bottomLeft"
          title="查看审批人"
          content={getLeaderContent(item.value[0])}
          overlayStyle={{ width: '300px' }}
        >
          <CheckOutlined style={{ marginRight: 20 }} />
          {Math.min(item.value[0], leaderData?.length)}级主管审批
        </Popover>
      </div>
    );
  }
  if (item.type == TYPE.ROLE) {
    let label = item.label || '';
    const names = item.value.map((id) => {
      const role = roleList.find((cur: any) => cur.ID == id);
      return role?.Name;
    });
    let title = `从${names.join('、')}选择`;
    let userNames = [];
    if (value?.length > 0) {
      userNames = value.map(
        (id: number) => userList.find((cur: any) => cur.ID == id)?.CName,
      );
    }
    return (
      <div
        style={{
          marginBottom: 20,
          cursor: 'pointer',
          display: 'flex',
          justifyContent: 'space-between',
        }}
      >
        <div>
          <div style={{ fontSize: '18px' }}>{label}</div>
          <div style={{ fontSize: '14px', color: 'gray' }}>{title}</div>
        </div>
        <Popover
          placement="bottomLeft"
          title={'选择审批人'}
          content={content}
          trigger="click"
          overlayStyle={{ width: '300px' }}
          onOpenChange={handleOpen}
          style={{ marginBottom: 20, overflow: 'auto' }}
        >
          <Space>
            {userNames.join('、')}
            <PlusSquareOutlined style={{ fontSize: '36px', color: 'gray' }} />
          </Space>
        </Popover>
      </div>
    );
  }

  let label = item.label || '';

  let title = item.is_cc
    ? `抄送${item.value.length}人`
    : `${item.value.length}人审批`;
  const names = item.value.map((id) => {
    const user = userList.find((cur: any) => cur.ID == id);
    return user?.CName;
  });

  return (
    <div
      style={{
        marginBottom: 20,
        display: 'flex',
        justifyContent: 'space-between',
      }}
    >
      <div>
        <div style={{ fontSize: '18px' }}>{label}</div>
        <div style={{ fontSize: '14px', color: 'gray' }}>{title}</div>
      </div>
      {names.join('、')}
    </div>
  );
};

export default connect(({ user }: any) => ({
  roleList: user.roleList,
}))(ApprovalProcess);
