import { defineStore } from "pinia";
import loadingStore from "./loading";
import pinia from '@/stores/main.js';
import {useToast} from 'vue-toast-notification';
import 'vue-toast-notification/dist/theme-sugar.css';
import moment from "moment";
import { Decimal } from 'decimal.js';
import abbreviateNumber from '@/module/abbreviateNumber.js';

const loading = loadingStore(pinia);
const $toast = useToast();

// Delay loading and toast 待模組化
let delay = (s = 0) =>  new Promise((resolve, reject) => setTimeout(resolve, s));

export default defineStore('conformanceStore', {
  state: () => ({
    conformanceLogId: null,
    conformanceFilterId: null,
    conformanceTempCheckerId: null,
    allConformanceTask: [],
    allCfmSeqStart: [],
    allCfmSeqEnd: [],
    allProcessingTime: {},
    allWaitingTime: {},
    allCycleTime: {},
    allConformanceTempReportData: null,
    allIssueTraces: null,
    allTaskSeq: null,
    allCases: null,
    allLoopTraces: null,
    allLoopTaskSeq: null,
    allLoopCases: null,
    selectedRuleType: 'Have activity', // radio
    selectedActivitySequence: 'Start & End', // radio
    selectedMode: 'Directly follows', // radio
    selectedProcessScope: 'End to end', // radio
    selectedActSeqMore: 'All', // radio
    selectedActSeqFromTo: 'From', // radio
    infinite404: null,
    isStartSelected: null, // start & end 連動先選擇 start
    isEndSelected: null, // start & end 連動先選擇 end
  }),
  getters: {
    conformanceAllTasks: state => {
      return state.allConformanceTask;
    },
    conformanceTask: state => {
      return state.allConformanceTask.map(i => i.label);
    },
    cfmSeqStart: state => {
      return state.allCfmSeqStart;
    },
    cfmSeqEnd: state => {
      return state.allCfmSeqEnd;
    },
    cfmPtEteWhole: state => {
      return state.allProcessingTime.end_to_end.whole;
    },
    cfmPtEteStart: state => {
      return state.allProcessingTime.end_to_end.starts_with;
    },
    cfmPtEteEnd: state => {
      return state.allProcessingTime.end_to_end.ends_with;
    },
    cfmPtEteSE: state => {
      return state.allProcessingTime.end_to_end.start_end;
    },
    cfmPtPStart: state => {
      return state.allProcessingTime.partial.starts_with;
    },
    cfmPtPEnd: state => {
      return state.allProcessingTime.partial.ends_with;
    },
    cfmPtPSE: state => {
      return state.allProcessingTime.partial.start_end;
    },
    cfmWtEteWhole: state => {
      return state.allWaitingTime.end_to_end.whole;
    },
    cfmWtEteStart: state => {
      return state.allWaitingTime.end_to_end.starts_with;
    },
    cfmWtEteEnd: state => {
      return state.allWaitingTime.end_to_end.ends_with;
    },
    cfmWtEteSE: state => {
      return state.allWaitingTime.end_to_end.start_end;
    },
    cfmWtPStart: state => {
      return state.allWaitingTime.partial.starts_with;
    },
    cfmWtPEnd: state => {
      return state.allWaitingTime.partial.ends_with;
    },
    cfmWtPSE: state => {
      return state.allWaitingTime.partial.start_end;
    },
    cfmCtEteWhole: state => {
      return state.allCycleTime.end_to_end.whole;
    },
    cfmCtEteStart: state => {
      return state.allCycleTime.end_to_end.starts_with;
    },
    cfmCtEteEnd: state => {
      return state.allCycleTime.end_to_end.ends_with;
    },
    cfmCtEteSE: state => {
      return state.allCycleTime.end_to_end.start_end;
    },
    conformanceTempReportData: state => {
      return state.allConformanceTempReportData;
    },
    issueTraces: state => {
      return state.allIssueTraces;
    },
    taskSeq: state => {
      return state.allTaskSeq;
    },
    cases: state => {
      if(state.allCases !== null){
        const newData = state.allCases.map(c => {
          c.started_at = moment(c.started_at).format('YYYY/MM/DD HH:MM');
          c.completed_at = moment(c.completed_at).format('YYYY/MM/DD HH:MM');
          c.facets.map(fac => {
            switch(fac.type) {
              case 'duration-list':
                fac.value = fac.value.map(v => v !== null ? abbreviateNumber(new Decimal(v.toFixed(2))) : null);
                fac.value = fac.value.join(', ');
                break;
                default:
                break;
            };
            return fac;
          });
          c.attributes.map(att => {
            switch (att.type) {
              case 'date':
                att.value = att.value !== null ? moment(att.value).format('YYYY/MM/DD HH:MM:ss') : null;
                break;
              case 'float':
                att.value = att.value !== null ? new Decimal(att.value).toFixed(2) : null;
                break
              default:
                break;
            }
            return att;
          });
          const { facets, attributes, ...rest } = c;
          return { ...rest, facets, attributes };
        });
        return newData
      };
    },
    loopTraces: state => {
      return state.allLoopTraces;
    },
    loopTaskSeq: state => {
      return state.allLoopTaskSeq;
    },
    loopCases: state => {
      if(state.allLoopCases !== null){
        const newData = state.allLoopCases.map(c => {
          c.started_at = moment(c.started_at).format('YYYY/MM/DD HH:MM');
          c.completed_at = moment(c.completed_at).format('YYYY/MM/DD HH:MM');
          c.attributes.map(att => {
            switch (att.type) {
              case 'date':
                att.value = att.value !== null ? moment(att.value).format('YYYY/MM/DD HH:MM:ss') : null;
                break;
              case 'float':
                att.value = att.value !== null ? new Decimal(att.value).toFixed(2) : null;
                break
              default:
                break;
            }
            return att;
          });
          return c;
        });
        return newData;
      };
    },
  },
  actions: {
    /**
     * fetch Log Conformance Parameters api for Rule Settings.
     */
    async getLogConformanceParams() {
      let logId = this.conformanceLogId;
      const api = `/api/log-checkers/params?log_id=${logId}`;

      try {
        const response = await this.$axios.get(api);
        this.allConformanceTask = response.data.tasks;
        this.allCfmSeqStart = response.data.sources;
        this.allCfmSeqEnd = response.data.sinks;
        this.allProcessingTime = response.data.processing_time;
        this.allWaitingTime = response.data.waiting_time;
        this.allCycleTime = response.data.cycle_time;
      } catch(error) {
        await delay();
        loading.isLoading = true;
        await delay(1000);
        loading.isLoading = false;
        await delay(500);
        $toast.default('Failed to load the Conformance Parameters.',{position: 'bottom'});
      }
    },
    /**
     * Creates a new temporary checker for a log.
     */
    async addLogConformanceTempCheckerId(data) {
      let logId = this.conformanceLogId;
      const api = `/api/temp-log-checkers?log_id=${logId}`;

      try {
        const response = await this.$axios.post(api, data);
        this.conformanceTempCheckerId = response.data.id;
      } catch(error) {
        await delay();
        loading.isLoading = true;
        await delay(1000);
        loading.isLoading = false;
        await delay(500);
        $toast.default('Failed to add the Temporary Checker for a log.',{position: 'bottom'});
      }
    },
    /**
     * Get the Temporary Log Conformance Report
     */
    async getLogConformanceTempReport() {
      let checkerId = this.conformanceTempCheckerId;
      const api = `/api/temp-log-checkers/${checkerId}`;

      try {
        const response = await this.$axios.get(api);
        this.allConformanceTempReportData = response.data;
      } catch(error) {
        await delay();
        loading.isLoading = true;
        await delay(1000);
        loading.isLoading = false;
        await delay(500);
        $toast.default('Failed to Get the Temporary Log Conformance Report.',{position: 'bottom'});

      }
    },
    /**
     * Get the detail of a temporary log conformance issue.
     */
    async getLogConformanceIssue(issueNo) {
      let checkerId = this.conformanceTempCheckerId;
      const api = `/api/temp-log-checkers/${checkerId}/issues/${issueNo}`;

      try {
        const response = await this.$axios.get(api);
        this.allIssueTraces = response.data.traces;
      } catch(error) {
        await delay();
        loading.isLoading = true;
        await delay(1000);
        loading.isLoading = false;
        await delay(500);
        $toast.default('Failed to Get the detail of a temporary log conformance issue.',{position: 'bottom'});
      };
    },
    /**
     * Get the Trace Details of a Temporary Log Conformance lssue.
     */
    async getLogConformanceTraceDetail(issueNo, traceId, start) {
      let checkerId = this.conformanceTempCheckerId;
      const api = `/api/temp-log-checkers/${checkerId}/issues/${issueNo}/traces/${traceId}?start=${start}&page_size=20`;

      try {
        const response = await this.$axios.get(api);
        this.allTaskSeq = response.data.task_seq;
        this.allCases = response.data.cases;
        return response.data.cases;
      } catch(error) {
        if(error.response.status === 404) this.infinite404 = 404;
        else {
          await delay();
          loading.isLoading = true;
          await delay(1000);
          loading.isLoading = false;
          await delay(500);
          $toast.default('Failed to Get the detail of a temporary log conformance issue.',{position: 'bottom'});
        };
      };
    },
    /**
     * Get the Details of a Temporary Log Conformance Loop.
     */
    async getLogConformanceLoop(loopNo) {
      let checkerId = this.conformanceTempCheckerId;
      let api = `/api/temp-log-checkers/${checkerId}/loops/${loopNo}`;

      try {
        const response = await this.$axios.get(api);
        this.allLoopTraces = response.data.traces;
      } catch(error) {
        await delay();
        loading.isLoading = true;
        await delay(1000);
        loading.isLoading = false;
        await delay(500);
        $toast.default('Failed to Get the detail of a temporary log conformance loop.',{position: 'bottom'});
      };
    },
    /**
     * Get the Trace Details of a Temporary Log Conformance Loops.
     */
    async getLogConformanceLoopsTraceDetail(loopNo, traceId, start) {
      let checkerId = this.conformanceTempCheckerId;
      const api = `/api/temp-log-checkers/${checkerId}/loops/${loopNo}/traces/${traceId}?start=${start}&page_size=20`;

      try {
        const response = await this.$axios.get(api);
        this.allLoopTaskSeq = response.data.task_seq;
        this.allLoopCases = response.data.cases;
        return response.data.cases;
      } catch(error) {
        if(error.response.status === 404) this.infinite404 = 404;
        else {
          await delay();
          loading.isLoading = true;
          await delay(1000);
          loading.isLoading = false;
          await delay(500);
          $toast.default('Failed to Get the detail of a temporary log conformance loop.',{position: 'bottom'});
        };
      };
    },
  },
})
