import { defineStore } from "pinia";
import type { CreateProtocolViewModel, SyncProtocolViewModel } from "@/viewmodels/admin/protocol.models";
import { http } from "@/serverCom";
import type { AxiosResponse } from "axios";
import type { ProtocolViewModel } from "@/viewmodels/admin/protocol.models";
import cloneDeep from "lodash.clonedeep";
import isEqual from "lodash.isequal";
import difference from "lodash.difference";

export const useProtocolStore = defineStore("protocol", {
  state: () => {
    return {
      protocols: [] as Array<ProtocolViewModel & { tab_pos: number }>,
      totalCount: 0 as number,
      loading: "loading" as "loading" | "fetched" | "failed",
      activeProtocol: null as number | null,
      activeProtocolObj: null as ProtocolViewModel | null,
      origin: null as ProtocolViewModel | null,
      loadingActive: "loading" as "loading" | "fetched" | "failed",
      syncingProtocol: "synced" as "synced" | "syncing" | "detectedChanges" | "failed",
    };
  },
  getters: {
    detectedChangeProtocol: (state) =>
      !isEqual(state.origin, state.activeProtocolObj) && state.syncingProtocol != "syncing",
  },
  actions: {
    setProtocolSyncingState(state: "synced" | "syncing" | "detectedChanges" | "failed") {
      this.syncingProtocol = state;
    },
    fetchProtocols(offset = 0, count = 25, clear = false) {
      if (clear) this.protocols = [];
      this.loading = "loading";
      http
        .get(`/admin/protocol?offset=${offset}&count=${count}`)
        .then((result) => {
          this.totalCount = result.data.total;
          result.data.protocols
            .filter((elem: ProtocolViewModel) => this.protocols.findIndex((m) => m.id == elem.id) == -1)
            .map((elem: ProtocolViewModel, index: number): ProtocolViewModel & { tab_pos: number } => {
              return {
                ...elem,
                tab_pos: index + offset,
              };
            })
            .forEach((elem: ProtocolViewModel & { tab_pos: number }) => {
              this.protocols.push(elem);
            });
          this.loading = "fetched";
        })
        .catch((err) => {
          this.loading = "failed";
        });
    },
    fetchProtocolByActiveId() {
      this.loadingActive = "loading";
      http
        .get(`/admin/protocol/${this.activeProtocol}`)
        .then((res) => {
          this.origin = res.data;
          this.activeProtocolObj = cloneDeep(this.origin);
          this.loadingActive = "fetched";
        })
        .catch((err) => {
          this.loadingActive = "failed";
        });
    },
    fetchProtocolById(id: number) {
      return http.get(`/admin/protocol/${id}`);
    },
    async createProtocol(protocol: CreateProtocolViewModel): Promise<AxiosResponse<any, any>> {
      const result = await http.post(`/admin/protocol`, {
        title: protocol.title,
        date: protocol.date,
      });
      this.fetchProtocols();
      return result;
    },
    async synchronizeActiveProtocol(): Promise<void> {
      if (this.origin == null || this.activeProtocolObj == null) return;

      this.syncingProtocol = "syncing";
      await http
        .patch(`/admin/protocol/${this.origin.id}/synchronize`, {
          title: this.activeProtocolObj.title,
          date: this.activeProtocolObj.date,
          starttime: this.activeProtocolObj.starttime,
          endtime: this.activeProtocolObj.endtime,
          summary: this.activeProtocolObj.summary,
        })
        .then((res) => {
          this.syncingProtocol = "synced";
        })
        .catch((err) => {
          this.syncingProtocol = "failed";
        });
      this.fetchProtocolById(this.origin.id)
        .then((res) => {
          this.origin = res.data;
          if (this.detectedChangeProtocol) this.syncingProtocol = "detectedChanges";
        })
        .catch((err) => {});
    },
  },
});
