import { defineStore } from "pinia";
import axios from "axios";
import moment from 'moment';
import apiError from '@/module/apiError.js';
import Swal from 'sweetalert2';
import { uploadFailedFirst, uploadFailedSecond, uploadloader, uploadSuccess } from '@/module/alertModal.js';
import pinia from '@/stores/main.js';
import loadingStore from '@/stores/loading.js';

const loading = loadingStore(pinia);

export default defineStore('filesStore', {
  state: () => ({
    allEventFiles: [
      {
        parentLog: '',
        fileType: '',
        ownerName: '',
      }
    ],
    switchFilesTagData: {
      ALL: ['Log', 'Filter', 'Rule', 'Design'],
      DISCOVER: ['Log', 'Filter', 'Rule'],
      COMPARE: ['Log','Filter'],
      DESIGN: ['Log', 'Design'],
    },
    filesTag: 'ALL',
    httpStatus: 200,
    uploadId: null,
    allUploadDetail: null,
    uploadLogId: null,
    uploadFileName: null,
    allDependentsData: null,
  }),
  getters: {
    /**
     * Get allFiles and switch files tag
     */
    allFiles: state => {
      let result = state.allEventFiles;
      let data = state.switchFilesTagData;
      let filesTag = state.filesTag;

      result = result.filter(file => data[filesTag].includes(file.fileType));

      return result;
    },
    /**
     * Get upload preview
     */
    uploadDetail: state => {
      return state.allUploadDetail;
    },
    /**
     * Get dependents of files data
     */
    dependentsData: state => {
      return state.allDependentsData;
    }
  },
  actions: {
    /**
     * Fetch All Files api
     */
    async fetchAllFiles() {
      const api = '/api/files';
      let icon = '';
      let fileType = '';
      let parentLog = '';

      try {
        const response = await axios.get(api);

        this.allEventFiles = response.data;
        this.allEventFiles.map(o => {
          switch (o.type) {
            case 'log':
              icon = 'work_history';
              fileType = 'Log';
              parentLog = o.name;
              break;
            case 'filter':
              icon = 'tornado';
              fileType = 'Filter';
              parentLog = o.parent.name;
              break;
            case 'log-check':
            case 'filter-check':
              icon = 'local_police';
              fileType = 'Rule';
              parentLog = o.parent.name;
              break;
            case 'design':
              icon = 'shape_line';
              break;
          }
          o.icon = icon;
          o.parentLog = parentLog;
          o.fileType = fileType;
          o.ownerName = o.owner.name;
          o.updated_base = o.updated_at;
          o.accessed_base = o.accessed_at;
          o.updated_at = moment(o.updated_at).utcOffset('+08:00').format('YYYY-MM-DD HH:mm');
          o.accessed_at = o.accessed_at ? moment(o.accessed_at).utcOffset('+08:00').format('YYYY-MM-DD HH:mm') : null;
        });
      } catch(error) {
        apiError(error, 'Failed to load the files.');
      };
    },
    /**
     * Uploads a CSV log file. 第一階段上傳
     * @param {Object} fromData
     */
    async upload(fromData) {
      const api = '/api/logs/csv-uploads';
      const config = {
        data: true,
        headers: {
          'Content-Type': 'multipart/form-data',
        },
      };

      uploadloader(); // 進度條
      try {
        const response = await axios.post(api, fromData, config);

        this.uploadId = response.data.id;
        this.$router.push({name: 'Upload'});
        Swal.close(); // 關閉進度條
      } catch(error) {
        if(error.response.status === 422) {
          // msg: 'not in UTF-8' | 'insufficient columns' | 'the csv file is empty' | 'the filename does not ends with .csv'
          // type: 'encoding' | 'insufficient_columns' | 'empty' | 'name_suffix'
          let detail = error.response.data.detail;

          uploadFailedFirst(detail[0].type, detail[0].msg, detail[0].loc[2]);
        } else {
          Swal.close(); // 關閉進度條
          apiError(error, 'Failed to upload the files.');
        }
      }
    },
    /**
     * Fetch upload detail
     */
    async getUploadDetail() {
      const uploadId = this.uploadId;
      const api = `/api/logs/csv-uploads/${uploadId}`;

      try {
        const response = await axios.get(api);
        this.allUploadDetail = response.data.preview;
      } catch(error) {
        apiError(error, 'Failed to get upload detail.');
      }
    },
    /**
     * Add a Log from an Uploaded CSV Log File. 第二階段上傳
     * @param {Object} data
     */
    async uploadLog(data) {
      const uploadId = this.uploadId;
      const api = `/api/logs/csv-uploads/${uploadId}`;

      uploadloader(); // 進度條
      try {
        const response = await axios.post(api, data);

        this.uploadLogId = await response.data.id;
        await Swal.close(); // 關閉進度條
        await this.rename(); // 改檔名
        await uploadSuccess();
        this.$router.push({name: 'Files'});
      } catch(error) {
        if(error.response.status === 422) {
          let detail = [...error.response.data.detail];

          uploadFailedSecond(detail);
        } else {
          Swal.close(); // 關閉進度條
          apiError(error, 'Failed to upload the log files.');
        }
      }
    },
    /**
     * Rename a Log
     * @param { string } type log | filter | log-check | filter-check
     * @param { number } id
     * @param { string } name
     */
    async rename(type, id, fileName) {
      // 先判斷有沒有 uploadLogId，有就設定 id 和 type；再判斷檔案型別。
      if(this.uploadId && this.uploadFileName) {
        type = 'log';
        id = this.uploadLogId;
        fileName = this.uploadFileName;
      }

      let api;
      let data = {"name": fileName};

      switch (type) {
        case 'log':
          api = `/api/logs/${id}/name`;
          break;
        case 'filter':
          api = `/api/filters/${id}/name`;
          break;
        case 'log-check':
          api = `/api/log-checks/${id}/name`;
          break;
        case 'filter-check':
          api = `/api/filter-checks/${id}/name`;
          break;
      }
      try {
        const response = await axios.put(api, data);
        this.uploadFileName = null;
        await this.fetchAllFiles();
      } catch(error) {
        apiError(error, 'Failed to rename.');
      }
    },
    /**
     * Get the Dependents of the files
     * @param { string } type log | filter | log-check | filter-check
     * @param { number } id
     */
    async getDependents(type, id) {
      let api;

      switch (type) {
        case 'log':
          api = `/api/logs/${id}/dependents`;
          break;
        case 'filter':
          api = `/api/filters/${id}/dependents`;
          break;
        case 'log-check':
          api = `/api/log-checks/${id}/dependents`;
          break;
        case 'filter-check':
          api = `/api/filter-checks/${id}/dependents`;
          break;
      }
      try {
        const response = await axios.get(api);
        this.allDependentsData = response.data;
      } catch(error) {
        apiError(error, 'Failed to get Dependents of the files.');
      }
    },
    /**
     * Delete file
     * @param { string } type log | filter | log-check | filter-check
     * @param { number } id
     */
    async deleteFile(type, id) {
      let api;

      if(id == null || isNaN(id)) {
        console.error('Delete File API:', id);
        return $toast.default('Delete File API Error.', {position: 'bottom'});
      };
      loading.isLoading = true;
      switch (type) {
        case 'log':
          api = `/api/logs/${id}`;
          break;
        case 'filter':
          api = `/api/filters/${id}`;
          break;
        case 'log-check':
          api = `/api/log-checks/${id}`;
          break;
        case 'filter-check':
          api = `/api/filter-checks/${id}`;
          break;
      }
      try {
        const response = await axios.delete(api);
        await this.fetchAllFiles();
      } catch(error) {
        apiError(error, 'Failed to delete.');
      } finally {
        loading.isLoading = false;
      }
    },
    /**
     * Download file as CSV
     * @param { string } type log | filter | log-check | filter-check
     * @param { number } id
     * @param { string } fileName
     */
    async downloadFileCSV(type, id, fileName) {
      let api;

      switch (type) {
        case 'log':
          api = `/api/logs/${id}/csv`;
          break;
        case 'filter':
          api = `/api/filters/${id}/csv`;
          break;
        // case 'log-check':
        //   api = `/api/log-checks/${id}/csv`;
        //   break;
        // case 'filter-check':
        //   api = `/api/filter-checks/${id}/csv`;
        //   break;
        default:
          return;
      }
      try {
        const response = await axios.get(api);
        const csvData = response.data;
        const blob = new Blob([csvData], { type: 'text/csv' });
        const url = window.URL.createObjectURL(blob);
        const link = document.createElement('a');

        link.href = url;
        link.download = `${fileName}.csv`;
        link.click();
        window.URL.revokeObjectURL(url);
      } catch(error) {
        apiError(error, 'Failed to delete.');
      }
    },
  },
})
