import makeAutoObservable from "mobx-store-inheritance";
import { DataSetHttpRepository } from "./dataset_http_repository";
import { Drawer, UiErrorState } from "../../core/store/base_store";
import { HttpError } from "../../core/repository/core_http_repository";
import { DataSetModel, IDatasetModel, ProcessStatus } from "./dataset_model";
import { message } from "antd";
import { UUID } from "../all_projects/data/project_http_repository";
import { SocketRepository, socketRepository } from "../../core/repository/core_socket_repository";
import { Parts } from "../details/details_http_repository";

export enum DrawersDataset {
  NewDataset = "Новый датасет",
  FormBuilderDrawer = "Редактировать датасет",
}
 
export class DataSetStore extends UiErrorState<HttpError> {
  dataSetRepository: DataSetHttpRepository;
  parts?: Parts[];
  datasets?: IDatasetModel[];
  activeProject: UUID;
  dataSetModel = DataSetModel.empty();
  drawers: Drawer[];
  socketRepository: SocketRepository;
  titleDrawer: string = DrawersDataset.NewDataset;

  constructor() {
    super();
    this.socketRepository = socketRepository;
    this.dataSetRepository = new DataSetHttpRepository();
    this.drawers = Object.entries(DrawersDataset).map((k, v) => {
      return {
        name: k.at(1) ?? "",
        status: false,
      };
    });
    makeAutoObservable(this);
    socketRepository.on((e) => {
      if (e.event === "realtime") {
        if (e.payload !== undefined && e.payload.value !== undefined && e.payload.value.id !== undefined) {
          this.updateDatasetStatus(String(e.payload.value.id), ProcessStatus.END);
        }
        if (e.payload !== undefined && e.payload.error !== undefined && e.payload.error.id !== undefined) {
          this.updateDatasetStatus(String(e.payload.error.id), ProcessStatus.ERROR);
        }
      }
    });
  }
  updateDatasetStatus(id: string, status: ProcessStatus) {
    this.datasets = this.datasets?.map((el) => {
      if (el._id.isEqual(id)) {
        el.processStatus = status;
      }
      return el;
    });
  }
  openEmptyCard() {
    this.dataSetModel = DataSetModel.empty();
    this.titleDrawer = DrawersDataset.NewDataset;
    this.editDrawer(DrawersDataset.NewDataset, true);
  }

  setNewDatasetName(e: string): void {
    this.dataSetModel.name = e;
  }

  setSkillSelected(el: string): void {
    this.dataSetModel.datasetType = el;
  }

  skillIsSelected(el: string): boolean {
    return el === this.dataSetModel.datasetType;
  }

  assetStatus(name: string): boolean {
    return this.dataSetModel.dataSetObjects.includes(name);
  }

  datasetCheckBox(part: Parts): void {
    if (this.assetStatus(part.name)) {
      this.dataSetModel.dataSetObjects = this.dataSetModel.dataSetObjects.filter((el) => !el.isEqual(part.name));
    } else {
      this.dataSetModel.dataSetObjects.push(part.name);
    }
  }

  editDrawer(drawerName: DrawersDataset, status: boolean): void {
    this.drawers = this.drawers.map((el) => {
      if (el.name === drawerName) {
        el.status = status;
      }
      return el;
    });
  }

  editDataset(id: string) {
    this.titleDrawer = DrawersDataset.FormBuilderDrawer;
    this.dataSetModel = DataSetModel.fromIDatasetModel(this.datasets?.find((el) => el._id === id) as IDatasetModel);
    this.editDrawer(DrawersDataset.NewDataset, true);
  }

  deleteDataset = async (id: string) => {
    (await this.dataSetRepository.deleteDataset(id)).fold(
      async () => {
        message.success("датасет удален");
        await this.getDatasets();
      },
      async (e) => message.error(e.message)
    );
  };

  runProcess = async (id: string): Promise<void> => {
    (await this.dataSetRepository.isRunningProcess()).fold(
      async (s) => {
        (await this.dataSetRepository.execDatasetProcess(id)).fold(
          () => {
            this.updateDatasetStatus(id, ProcessStatus.RUN);
            message.success("Процесс запущен");
          },
          (e) => message.error(e.message)
        );
      },
      async (e) => message.error(e.message)
    );
  };
  errorHandingStrategy = (error: HttpError) => {
    message.error(error.message);
  };

  saveDataset(): void {
    this.dataSetModel.project = this.activeProject.id;
    this.dataSetModel.isValid().fold(
      async () => {
        if (this.dataSetModel.isNew) {
          (await this.dataSetRepository.saveDataSet(this.dataSetModel)).fold(
            async () => {
              message.success("Датасет сохранен");
              await this.getDatasets();
              this.editDrawer(DrawersDataset.NewDataset, false);
            },
            async (error) => message.error(error.message)
          );
        } else {
          this.dataSetModel.processStatus = ProcessStatus.NEW;
          (await this.dataSetRepository.editDataset(this.dataSetModel)).fold(
            async () => {
              message.success("Настройки датасета измнены");
              await this.getDatasets();
              this.editDrawer(DrawersDataset.NewDataset, false);
            },
            async (error) => message.error(error.message)
          );
        }
      },
      async (error) => message.error(error)
    );
  }

  init = async () => {
    await this.mapOk("parts", this.dataSetRepository.getAssetsActiveProject());
    await this.getDatasets();
    await this.mapOk("activeProject", this.dataSetRepository.getActiveProjectId());
  };
  getDatasets = async () => {
    await this.mapOk("datasets", this.dataSetRepository.getDatasetsActiveProject());
  };
}
