window.app = Vue.createApp({
  el: '#vue',
  mixins: [window.windowMixin],
  data() {
    return {
      auditEntries: [],
      searchData: {
        user_id: '',
        ip_address: '',
        request_type: '',
        component: '',
        request_method: '',
        response_code: '',
        path: ''
      },
      searchOptions: {
        component: [],
        request_method: [],
        response_code: []
      },
      auditTable: {
        columns: [
          {
            name: 'created_at',
            align: 'center',
            label: 'Date',
            field: 'created_at',
            sortable: true
          },
          {
            name: 'duration',
            align: 'left',
            label: 'Duration (sec)',
            field: 'duration',
            sortable: true
          },
          {
            name: 'component',
            align: 'left',
            label: 'Component',
            field: 'component',
            sortable: false
          },
          {
            name: 'request_method',
            align: 'left',
            label: 'Method',
            field: 'request_method',
            sortable: false
          },
          {
            name: 'response_code',
            align: 'left',
            label: 'Code',
            field: 'response_code',
            sortable: false
          },
          {
            name: 'user_id',
            align: 'left',
            label: 'User Id',
            field: 'user_id',
            sortable: false
          },
          {
            name: 'ip_address',
            align: 'left',
            label: 'IP Address',
            field: 'ip_address',
            sortable: false
          },

          {
            name: 'path',
            align: 'left',
            label: 'Path',
            field: 'path',
            sortable: false
          }
        ],
        pagination: {
          sortBy: 'created_at',
          rowsPerPage: 10,
          page: 1,
          descending: true,
          rowsNumber: 10
        },
        search: null,
        hideEmpty: true,
        loading: false
      },
      auditDetailsDialog: {
        data: null,
        show: false
      }
    }
  },

  async created() {
    await this.fetchAudit()
  },
  mounted() {
    this.initCharts()
  },

  methods: {
    formatDate(dateString) {
      return LNbits.utils.formatDateString(dateString)
    },
    async fetchAudit(props) {
      try {
        const params = LNbits.utils.prepareFilterQuery(this.auditTable, props)
        const {data} = await LNbits.api.request(
          'GET',
          `/audit/api/v1?${params}`
        )

        this.auditTable.pagination.rowsNumber = data.total
        this.auditEntries = data.data
        await this.fetchAuditStats(props)
      } catch (error) {
        console.warn(error)
        LNbits.utils.notifyApiError(error)
      } finally {
        this.auditTable.loading = false
      }
    },
    async fetchAuditStats(props) {
      try {
        const params = LNbits.utils.prepareFilterQuery(this.auditTable, props)
        const {data} = await LNbits.api.request(
          'GET',
          `/audit/api/v1/stats?${params}`
        )

        const request_methods = data.request_method.map(rm => rm.field)
        this.searchOptions.request_method = [
          ...new Set(this.searchOptions.request_method.concat(request_methods))
        ]
        this.requestMethodChart.data.labels = request_methods
        this.requestMethodChart.data.datasets[0].data = data.request_method.map(
          rm => rm.total
        )
        this.requestMethodChart.update()

        const response_codes = data.response_code.map(rm => rm.field)
        this.searchOptions.response_code = [
          ...new Set(this.searchOptions.response_code.concat(response_codes))
        ]
        this.responseCodeChart.data.labels = response_codes
        this.responseCodeChart.data.datasets[0].data = data.response_code.map(
          rm => rm.total
        )
        this.responseCodeChart.update()

        const components = data.component.map(rm => rm.field)
        this.searchOptions.component = [
          ...new Set(this.searchOptions.component.concat(components))
        ]
        this.componentUseChart.data.labels = components
        this.componentUseChart.data.datasets[0].data = data.component.map(
          rm => rm.total
        )

        this.componentUseChart.update()

        this.longDurationChart.data.labels = data.long_duration.map(
          rm => rm.field
        )
        this.longDurationChart.data.datasets[0].data = data.long_duration.map(
          rm => rm.total
        )

        this.longDurationChart.update()
      } catch (error) {
        console.warn(error)
        LNbits.utils.notifyApiError(error)
      }
    },
    async searchAuditBy(fieldName, fieldValue) {
      if (fieldName) {
        this.searchData[fieldName] = fieldValue
      }
      // remove empty fields
      this.auditTable.filter = Object.entries(this.searchData).reduce(
        (a, [k, v]) => (v ? ((a[k] = v), a) : a),
        {}
      )

      await this.fetchAudit()
    },
    showDetailsDialog(entry) {
      const details = JSON.parse(entry?.request_details || '')
      try {
        if (details.body) {
          details.body = JSON.parse(details.body)
        }
      } catch (e) {
        // do nothing
      }
      this.auditDetailsDialog.data = JSON.stringify(details, null, 4)
      this.auditDetailsDialog.show = true
    },
    shortify(value) {
      valueLength = (value || '').length
      if (valueLength <= 10) {
        return value
      }
      return `${value.substring(0, 5)}...${value.substring(valueLength - 5, valueLength)}`
    },
    initCharts() {
      this.responseCodeChart = new Chart(
        this.$refs.responseCodeChart.getContext('2d'),
        {
          type: 'doughnut',

          options: {
            responsive: true,

            plugins: {
              legend: {
                position: 'bottom'
              },
              title: {
                display: false,
                text: 'HTTP Response Codes'
              }
            },
            onClick: (_, elements, chart) => {
              if (elements[0]) {
                const i = elements[0].index
                this.searchAuditBy('response_code', chart.data.labels[i])
              }
            }
          },
          data: {
            datasets: [
              {
                label: '',
                data: [20, 10],
                backgroundColor: [
                  'rgb(100, 99, 200)',
                  'rgb(54, 162, 235)',
                  'rgb(255, 205, 86)',
                  'rgb(255, 5, 86)',
                  'rgb(25, 205, 86)',
                  'rgb(255, 205, 250)'
                ]
              }
            ],
            labels: []
          }
        }
      )
      this.requestMethodChart = new Chart(
        this.$refs.requestMethodChart.getContext('2d'),
        {
          type: 'bar',

          options: {
            responsive: true,
            maintainAspectRatio: false,
            plugins: {
              title: {
                display: false
              }
            },
            onClick: (_, elements, chart) => {
              if (elements[0]) {
                const i = elements[0].index
                this.searchAuditBy('request_method', chart.data.labels[i])
              }
            }
          },
          data: {
            datasets: [
              {
                label: '',
                data: [],
                backgroundColor: [
                  'rgb(255, 99, 132)',
                  'rgb(54, 162, 235)',
                  'rgb(255, 205, 86)',
                  'rgb(255, 5, 86)',
                  'rgb(25, 205, 86)',
                  'rgb(255, 205, 250)'
                ],
                hoverOffset: 4
              }
            ]
          }
        }
      )
      this.componentUseChart = new Chart(
        this.$refs.componentUseChart.getContext('2d'),
        {
          type: 'pie',
          options: {
            responsive: true,
            plugins: {
              legend: {
                position: 'xxx'
              },
              title: {
                display: false,
                text: 'Components'
              }
            },
            onClick: (_, elements, chart) => {
              if (elements[0]) {
                const i = elements[0].index
                this.searchAuditBy('component', chart.data.labels[i])
              }
            }
          },
          data: {
            datasets: [
              {
                data: [],
                backgroundColor: [
                  'rgb(255, 99, 132)',
                  'rgb(54, 162, 235)',
                  'rgb(255, 205, 86)',
                  'rgb(255, 5, 86)',
                  'rgb(25, 205, 86)',
                  'rgb(255, 205, 250)',
                  'rgb(100, 205, 250)',
                  'rgb(120, 205, 250)',
                  'rgb(140, 205, 250)',
                  'rgb(160, 205, 250)'
                ],
                hoverOffset: 4
              }
            ]
          }
        }
      )
      this.longDurationChart = new Chart(
        this.$refs.longDurationChart.getContext('2d'),
        {
          type: 'bar',
          options: {
            responsive: true,
            indexAxis: 'y',
            maintainAspectRatio: false,
            plugins: {
              legend: {
                title: {
                  display: false,
                  text: 'Long Duration'
                }
              }
            },
            onClick: (_, elements, chart) => {
              if (elements[0]) {
                const i = elements[0].index
                this.searchAuditBy('path', chart.data.labels[i])
              }
            }
          },
          data: {
            datasets: [
              {
                label: '',
                data: [],
                backgroundColor: [
                  'rgb(255, 99, 132)',
                  'rgb(54, 162, 235)',
                  'rgb(255, 205, 86)',
                  'rgb(255, 5, 86)',
                  'rgb(25, 205, 86)',
                  'rgb(255, 205, 250)',
                  'rgb(100, 205, 250)',
                  'rgb(120, 205, 250)',
                  'rgb(140, 205, 250)',
                  'rgb(160, 205, 250)'
                ],
                hoverOffset: 4
              }
            ]
          }
        }
      )
    }
  }
})
