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

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('allMapDataStore', {
  state: () => ({
    logId: null,
    traceId: 1,
    tempFilterId: null,
    createFilterId: null,
    filterName: null,
    allProcessMap: {},
    allBpmn: {},
    allStats: {},
    allInsights: {},
    allTrace: [],
    allCase: [],
    allTraceTaskSeq: [],
    allFilterTask: [],
    allFilterStartToEnd: [],
    allFilterEndToStart: [],
    allFilterTimeframe: {},
    allFilterTrace: [],
    httpStatus: 200,
    hasResultRule: null, // click Apply 後檢查是否有 Data
    temporaryData: [], // 沒被 apply all 的 Data
    postRuleData: [], // has-result API & temp-filters API 的 Data
    ruleData: [], // Funnle view's data
    isRuleData: [], // toggle button data
    allFunnelData: [],
    isUpdataFilter: false, // 是否成功儲存 Filter 檔
    selectTimeFrame: [], // user select time start and end
  }),
  getters: {
    processMap: state => {
      return state.allProcessMap;
    },
    bpmn: state => {
      return state.allBpmn;
    },
    stats: state => {
      return state.allStats;
    },
    insights: state => {
      return state.allInsights;
    },
    traces: state => {
      return state.allTrace;
    },
    cases: state => {
      return state.allCase;
    },
    traceTaskSeq: state => {
      return state.allTraceTaskSeq;
    },
    // All tasks
    filterTasks: state => {
      return state.allFilterTask;
    },
    // form start to end tasks
    filterStartToEnd: state => {
      return state.allFilterStartToEnd;
    },
    // form end to start tasks
    filterEndToStart: state => {
      return state.allFilterEndToStart;
    },
    filterTimeframe: state => {
      return state.allFilterTimeframe;
    },
    filterTrace: state => {
      return state.allFilterTrace;
    },
    allFunnels: state => {
      return state.allFunnelData;
    },
  },
  actions: {
    /**
     * fetch discover api, include '/process-map, /bpmn, /stats, /insights'.
     */
    async getAllMapData() {
      let logId = this.logId;
      let tempFilterId = this.tempFilterId;
      let createfilterId = this.createFilterId
      let api = '';

      // 先判斷暫存 再判斷 filter 最後 log
      if(tempFilterId != null) api = `/api/temp-filters/${tempFilterId}/discover`;
      else if(createfilterId!= null) api = `/api/filters/${createfilterId}/discover`;
      else api = `/api/logs/${logId}/discover`;

      try {
        const response = await this.$axios.get(api);
        this.allProcessMap = response.data.process_map;
        this.allBpmn = response.data.bpmn;
        this.allStats = response.data.stats;
        this.allInsights = response.data.insights;

        // if(this.httpStatus < 300) loading.isLoading = false;
      } catch(error) {
        this.httpStatus = error.request.status;
        await delay();
        loading.isLoading = true;
        await delay(1000);
        loading.isLoading = false;
        await delay(500);
        $toast.default('Failed to load the Map.',{position: 'bottom'});
      };
    },
    /**
     * fetch trace api.
     */
    async getAllTrace() {
      let logId = this.logId;
      const api = `/api/logs/${logId}/traces`;

      try {
        const response = await this.$axios.get(api);
        this.allTrace = response.data;

        // if(this.httpStatus < 300) loading.isLoading = false;
      } catch(error) {
        this.httpStatus = error.request.status;
        await delay();
        loading.isLoading = true;
        await delay(1000);
        loading.isLoading = false;
        await delay(500);
        $toast.default('Failed to load the Trace.',{position: 'bottom'});
      }
    },
    /**
     * fetch trace detail api.
     */
    async getTraceDetail() {
      let logId = this.logId;
      let traceId = this.traceId;
      const api = `/api/logs/${logId}/traces/${traceId}`;

      try {
        const response = await this.$axios.get(api);
        this.allTraceTaskSeq = response.data.task_seq;
        this.allCase = response.data.cases;
        this.allCase.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');
          return this.allCase;
        });

        // if(this.httpStatus < 300) loading.isLoading = false;
      } catch(error) {
        this.httpStatus = error.request.status;
        await delay();
        loading.isLoading = true;
        await delay(1000);
        loading.isLoading = false;
        await delay(500);
        $toast.default('Failed to load the Trace Detail.',{position: 'bottom'});
      };
    },
    /**
     * fetch Filter Parameters api.
     */
    async getFilterParams() {
      let logId = this.logId;
      const api = `/api/filters/params?log_id=${logId}`;

      try {
        const response = await this.$axios.get(api);
        this.allFilterTask = response.data.tasks;
        this.allFilterStartToEnd = response.data.sources;
        this.allFilterEndToStart = response.data.sinks;
        this.allFilterTimeframe = response.data.timeframe;
        this.allFilterTrace = response.data.trace;

        // if(this.httpStatus < 300) loading.isLoading = false;
      } catch(error) {
        this.httpStatus = error.request.status;
        await delay();
        loading.isLoading = true;
        await delay(1000);
        loading.isLoading = false;
        await delay(500);
        $toast.default('Failed to load the Filter Parameters.',{position: 'bottom'});
      };
    },
    /**
     * Test if the Filter Rules Result in Any Data
     */
    async checkHasResult() {
      let logId = this.logId;
      const api = `/api/filters/has-result?log_id=${logId}`;

      try {
        const response = await this.$axios.post(api, this.postRuleData)
        this.hasResultRule = response.data.result;

        // if(this.httpStatus < 300) loading.isLoading = false;
      } catch(error) {
        this.httpStatus = error.request.status;
        await delay();
        loading.isLoading = true;
        await delay(1000);
        loading.isLoading = false;
        await delay(500);
        $toast.default('Failed to load the Has Result.',{position: 'bottom'});
      };
    },
    /**
     * Add a New Temporary Filter
     */
    async addTempFilterId() {
      let logId = this.logId;
      const api = `/api/temp-filters?log_id=${logId}`;

      try {
        const response = await this.$axios.post(api, this.postRuleData)
        this.tempFilterId = response.data.id;

        // if(this.httpStatus < 300) loading.isLoading = false;
      } catch(error) {
        this.httpStatus = error.request.status;
        await delay();
        loading.isLoading = true;
        await delay(1000);
        loading.isLoading = false;
        await delay(500);
        $toast.default('Failed to add the Temporary Filters.',{position: 'bottom'});
      };
    },
    /**
     * Add a New Filter
     */
    async addFilterId(value) {
      let logId = this.logId;
      const api = `/api/filters?log_id=${logId}`;
      let createFilterObj = {
        name: value,
        rules: this.postRuleData
      };

      try {
        const response = await this.$axios.post(api, createFilterObj);
        this.createFilterId = response.data.id;
        this.tempFilterId = null;
      }catch(error) {
        this.httpStatus = error.request.status;
        await delay();
        loading.isLoading = true;
        await delay(1000);
        loading.isLoading = false;
        await delay(500);
        $toast.default('Failed to load the Filters.',{position: 'bottom'});
      };
    },
    /**
     * Get Filter Detail
     */
    async fetchFunnel(createfilterId) {
      const api = `/api/filters/${createfilterId}`;

      if(createfilterId){
        try {
          const response = await this.$axios.get(api);
          this.temporaryData = response.data.rules;
          this.logId = response.data.log.id;
          this.filterName = response.data.name;
        }catch(error) {
          this.httpStatus = error.request.status;
          await delay();
          loading.isLoading = true;
          await delay(1000);
          loading.isLoading = false;
          await delay(500);
          $toast.default('Failed to get Filter Detail.',{position: 'bottom'});
        }
      }
    },
    /**
     * Updata an Existing Filter
     */
    async updataFilter() {
      let createFilterId = this.createFilterId
      const api = `/api/filters/${createFilterId}`;
      const data = this.postRuleData;

      try {
        const response = await this.$axios.put(api, data);
        this.isUpdataFilter = response.status === 200;
      }catch(error) {
        this.httpStatus = error.request.status;
        await delay();
        loading.isLoading = true;
        await delay(1000);
        loading.isLoading = false;
        await delay(500);
        $toast.default('Failed to updata an Existing Filter.',{position: 'bottom'});
      }
    },
  },
})
