import KFModal from '@/components/KFModal';
import {
  DatasetData,
  ModelData,
  ProjectDependency,
  ResourceType,
  TrainTask,
  resourceConfig,
} from '@/pages/Dataset/config';
import { isEmpty } from '@/utils';
import { formatSource } from '@/utils/format';
import { to } from '@/utils/promise';
import { Typography, type ModalProps } from 'antd';
import classNames from 'classnames';
import { useEffect, useMemo, useState } from 'react';
import styles from './index.less';

type CompareData = {
  differences: Record<string, any>;
  version1: DatasetData | ModelData;
  version2: DatasetData | ModelData;
};

type FiledType<T extends DatasetData | ModelData> = {
  key: keyof T;
  text: string;
  format?: (data: any) => any;
};

interface VersionCompareModalProps extends Omit<ModalProps, 'onOk'> {
  versions: string[];
  resourceType: ResourceType;
  identifier: string;
  is_public: boolean;
  owner: string;
  repo_id: number;
}

const formatDatasets = (datasets?: DatasetData[]) => {
  if (!datasets || datasets.length === 0) {
    return undefined;
  }
  return datasets.map((item) => `${item.name}:${item.version}`).join(',');
};

const formatProject = (project?: ProjectDependency) => {
  if (!project) {
    return undefined;
  }
  return `${project.name}:${project.branch}`;
};

const formatTrainTask = (task?: TrainTask) => {
  if (!task) {
    return undefined;
  }
  return `${task.name}:${task.ins_id}`;
};

function VersionCompareModal({
  versions,
  resourceType,
  identifier,
  is_public,
  owner,
  repo_id,
  ...rest
}: VersionCompareModalProps) {
  const [compareData, setCompareData] = useState<CompareData | undefined>(undefined);
  const config = resourceConfig[resourceType];
  const fields: FiledType<DatasetData>[] | FiledType<ModelData>[] = useMemo(
    () =>
      resourceType === ResourceType.Dataset
        ? [
            {
              key: 'dataset_source',
              text: '数据来源',
              format: formatSource,
            },
            {
              key: 'train_task',
              text: '训练任务',
              format: formatTrainTask,
            },
            {
              key: 'processing_code',
              text: '处理代码',
              format: formatProject,
            },
            {
              key: 'version_desc',
              text: '版本描述',
            },
          ]
        : [
            {
              key: 'image',
              text: '训练镜像',
            },
            {
              key: 'project_depency',
              text: '训练代码',
              format: formatProject,
            },
            {
              key: 'train_datasets',
              text: '训练数据集',
              format: formatDatasets,
            },
            {
              key: 'test_datasets',
              text: '测试数据集',
              format: formatDatasets,
            },
            {
              key: 'model_source',
              text: '模型来源',
              format: formatSource,
            },
            {
              key: 'train_task',
              text: '训练任务',
              format: formatTrainTask,
            },
            {
              key: 'version_desc',
              text: '版本描述',
            },
          ],
    [resourceType],
  );

  useEffect(() => {
    // 获取对比数据
    const getServiceVersionCompare = async () => {
      const params = {
        versions,
        identifier,
        is_public,
        owner,
        repo_id,
      };
      const request = config.compareVersion;
      const [res] = await to(request(params));
      if (res && res.data) {
        setCompareData(res.data);
      }
    };

    getServiceVersionCompare();
  }, [versions, identifier, is_public, owner, repo_id, config]);

  // 获取值
  function getValue<T extends DatasetData | ModelData>(
    data: T,
    key: keyof T,
    format?: (data: any) => any,
  ) {
    const value = data[key];
    return format ? format(value) : value;
  }

  const {
    version1: v1 = {} as DatasetData | ModelData,
    version2: v2 = {} as DatasetData | ModelData,
    differences = {},
  } = compareData || {};

  const isDifferent = (key: string) => {
    return Object.keys(differences).includes(key);
  };

  return (
    <KFModal
      {...rest}
      title={`${config.name}版本对比`}
      width={825}
      footer={null}
      className={styles['version-compare']}
    >
      <div className={styles['version-compare__container']}>
        <div className={styles['version-compare__fields']}>
          <div className={styles['version-compare__fields__title']}>基础版本号</div>
          {fields.map(({ key, text }) => (
            <div
              className={classNames(styles['version-compare__fields__text'], {
                [styles['version-compare__fields__text--different']]: isDifferent(key),
              })}
              key={key}
            >
              {text}
            </div>
          ))}
        </div>
        <div className={styles['version-compare__left']}>
          <div className={styles['version-compare__left__title']}>
            <Typography.Text
              ellipsis={{ tooltip: v1.version }}
              style={{ width: '100%', lineHeight: 'inherit' }}
            >
              {v1.version}
            </Typography.Text>
          </div>
          {fields.map(({ key, format }) => {
            const text = getValue(v1, key as keyof typeof v1, format);
            return (
              <div
                key={key}
                className={classNames(styles['version-compare__left__text'], {
                  [styles['version-compare__left__text--different']]: isDifferent(key),
                })}
              >
                <Typography.Text ellipsis={{ tooltip: text }} style={{ width: '100%' }}>
                  {isEmpty(text) ? '--' : text}
                </Typography.Text>
              </div>
            );
          })}
        </div>
        <div className={styles['version-compare__right']}>
          <div className={styles['version-compare__right__title']}>
            <Typography.Text
              ellipsis={{ tooltip: v2.version }}
              style={{ width: '100%', lineHeight: 'inherit' }}
            >
              {v2.version}
            </Typography.Text>
          </div>
          {fields.map(({ key, format }) => {
            const text = getValue(v2, key as keyof typeof v2, format);
            return (
              <div
                key={key}
                className={classNames(styles['version-compare__right__text'], {
                  [styles['version-compare__right__text--different']]: isDifferent(key),
                })}
              >
                <Typography.Text ellipsis={{ tooltip: text }} style={{ width: '100%' }}>
                  {isEmpty(text) ? '--' : text}
                </Typography.Text>
              </div>
            );
          })}
        </div>
      </div>
    </KFModal>
  );
}

export default VersionCompareModal;
