import { Button, Col, Row, Space, message } from "antd";
import { useDicomUploader } from "./DicomUploader";
import { Series, Study } from "./DicomUploader/util";
import { DicomTable } from "./DicomTable";
import { useDomain } from "@/hook/useDomain";
import { useState } from "react";
import { User } from "@@/domain/User/entities/User";
import { limitConcurrency } from "./limitConcurrency";
import { CloudUploadOutlined, InboxOutlined } from "@ant-design/icons";
import { openOHIFViewer, flatternStudies, FlatStudyItem } from "./util";
import { DicomFileInfo } from "./DicomFileInfo";
import { UploadProgressModal } from "./UploadProgressModal";
import AssignModal from "./AssignModal";

interface DicomUploadProps {
  children?: JSX.Element;
}

export const DicomUpload = (props: DicomUploadProps) => {
  const [messageApi, contextHolder] = message.useMessage();
  const { UploadInput, fileCalculator, studys, isLoading } = useDicomUploader();
  const { dicomDomainService, userDomainService } = useDomain();
  const { dcmFileNum, totalFileNum, dcmFileSize } = fileCalculator;
  const [selectRows, setSelectedRows] = useState<Study[]>([]);
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [isAssignLoading, setIsAssignLoading] = useState(false);
  const [annotators, setAnnotators] = useState<User[]>([]);
  const [selectAnnotator, setSelectAnnotator] = useState<User | undefined>(
    undefined
  );
  const [visible, setVisible] = useState<boolean>(false);
  const [percent, setPercent] = useState<number>(0);

  /**
   * 单个序列阅片
   */
  const onUploadFiles = async (study: Study, series: Series) => {
    const { SeriesInstanceUID, subs } = series;
    const { StudyInstanceUID } = study;
    const instances = await dicomDomainService.existInPacs({
      SeriesInstanceUID,
      StudyInstanceUID,
    });
    // pacs已存在
    if (instances.length === subs.length) {
      openOHIFViewer(StudyInstanceUID, SeriesInstanceUID);
    } else {
      setVisible(true);
      limitConcurrency(
        series.subs.map((f: File) => () => dicomDomainService.upload2Pacs(f)),
        10,
        (completed, total) => {
          console.log(`${completed} out of ${total} tasks completed.`);
          setPercent(Math.floor((completed / total) * 100));
        },
        () => {
          setVisible(false);
          setPercent(0);
          openOHIFViewer(StudyInstanceUID, SeriesInstanceUID);
        }
      );
    }
  };

  /**
   * 返回不在pacs中的影像数据
   */
  const filterDicomPromise = () => {
    const items = flatternStudies(studys);
    // 过滤存在pacs中的序列
    const checkExistPromises = items.map(
      (item) =>
        new Promise(async (resolve) => {
          const instances = await dicomDomainService.existInPacs({
            SeriesInstanceUID: item.SeriesInstanceUID,
            StudyInstanceUID: item.StudyInstanceUID,
          });
          const existInPacs = instances.length === item.Files.length;
          resolve(existInPacs ? false : item);
        })
    ) as Promise<FlatStudyItem | false>[];
    return Promise.all(checkExistPromises);
  };

  /**
   * 上传全部
   */
  const onUploadEntiredDicom = () => {
    // 上传到pacs
    filterDicomPromise().then((result) => {
      const files = result.map((i) => (!i ? [] : i.Files)).flat();
      if (files.length === 0) return messageApi.info("全部影像均已存在pacs中");
      setVisible(true);
      limitConcurrency(
        files.map((f: File) => () => dicomDomainService.upload2Pacs(f)),
        10,
        (completed, total) => {
          console.log(`${completed} out of ${total} tasks completed.`);
          setPercent(Math.floor((completed / total) * 100));
        },
        () => {
          setVisible(false);
          setPercent(0);
        }
      );
    });
  };

  const onClickAssign = () => {
    // 检查是否全部传到pacs
    setIsAssignLoading(true);
    filterDicomPromise().then((result) => {
      const files = result.map((i) => (!i ? [] : i.Files)).flat();
      if (files.length !== 0) {
        setIsAssignLoading(false);
        return messageApi.info("请先上传全部影像到pacs");
      }
      userDomainService.getDmpAnnotators().then((res) => {
        setIsAssignLoading(false);
        setIsModalOpen(true);
        setAnnotators(res.data as User[]);
      });
    });
  };

  /**
   * 分配任务
   */
  const onAssignConfirm = () => {
    if (!selectAnnotator?.id) return;
    userDomainService.createArchiveTask(selectAnnotator, selectRows);
    setSelectAnnotator(undefined);
    setIsModalOpen(false);
  };

  return (
    <div style={{ padding: 20 }}>
      <Row style={{ paddingBottom: 20 }}>
        <Col span={24}>
          <Space>
            <UploadInput />
            <Button
              icon={<CloudUploadOutlined />}
              disabled={Number(dcmFileNum) === 0}
              type="primary"
              onClick={onUploadEntiredDicom}
            >
              上传全部
            </Button>
            <Button
              icon={<InboxOutlined />}
              disabled={selectRows.length === 0}
              type="primary"
              loading={isAssignLoading}
              onClick={onClickAssign}
            >
              分配
            </Button>
          </Space>
        </Col>
      </Row>
      <DicomFileInfo
        dcmFileNum={dcmFileNum}
        dcmFileSize={dcmFileSize}
        totalFileNum={totalFileNum}
      />
      <DicomTable
        studys={studys}
        loading={isLoading}
        onSelectedRows={(rows) => setSelectedRows(rows)}
        onUploadFiles={onUploadFiles}
      />
      <AssignModal
        isOpen={isModalOpen}
        options={annotators.map((a) => ({
          value: a.id,
          label: a.username,
        }))}
        value={selectAnnotator?.id as number}
        onSelectAnnotator={(id: number) =>
          setSelectAnnotator(annotators.find((a) => a.id === id))
        }
        onConfirm={onAssignConfirm}
        onCancel={() => setIsModalOpen(false)}
      />
      <UploadProgressModal
        title="上传影像中"
        isOpen={visible}
        percent={percent}
      />
      {contextHolder}
    </div>
  );
};
