const axios = require('axios').default
const fs = require('fs')
const Path = require('path')

function mkdirsSync(dirname) {
  if (fs.existsSync(dirname)) {
    return true
  } else {
    if (mkdirsSync(Path.dirname(dirname))) {
      fs.mkdirSync(dirname)
      return true
    }
  }
}
const fileTemplate = `/**
 * 该文件由插件根据doc.html在启动项目时自动生成，请勿修改(修改了也会被覆盖
 */

import request from '@/utils/request'
`
const functionCodeGener = function(meta) {
  const functionParams = []
  if (Array.isArray(meta.params) && meta.params.length > 0) {
    functionParams.push('params')
  }
  if (Array.isArray(meta.data) && meta.data.length > 0) {
    functionParams.push('data')
  }
  if (Array.isArray(meta.formData) && meta.formData.length > 0) {
    functionParams.push('formData')
  }
  return `
/**
 * ${meta.comment}
 */
export function ${meta.name}(${functionParams.join(', ')}) {
  return request({
    method: '${meta.method}',
    url: '${meta.url}'${meta.requestType ? ',\n    requestType: \'' + meta.requestType + '\'' : ''}${functionParams.includes('params') ? ',\n    params' : ''}${functionParams.includes('data') || functionParams.includes('formData') ? ',\n    data' + (functionParams.includes('formData') ? ': formData' : '') : ''}
  })
}
`
}
module.exports = class Genapi {
  constructor(apiUrl, output = 'build') {
    this.apiUrl = apiUrl[apiUrl.length - 1] === '/' ? apiUrl.slice(0, apiUrl.length - 1) : apiUrl
    this.output = output
  }
  apply(compiler) {
    compiler.hooks.environment.tap('Genapi', async(compilation, callback) => {
      const projectPath = Path.join(__dirname, '../')
      const apiPath = Path.join(projectPath, 'src/api/', this.output)
      axios({
        url: this.apiUrl + '/swagger-resources',
        method: 'get'
      }).then(({ data }) => {
        const resultFile = {}
        Promise.all(data.map((apiScope) => {
          return axios({
            url: this.apiUrl + '/v2/api-docs',
            params: {
              group: apiScope.name
            },
            method: 'get'
          }).then(({ data }) => {
            const {
              basePath,
              paths
            } = data
            for (const _path in paths) {
              const path = _path.replace(new RegExp('^' + basePath, 'g'), '')
              const pathSplit = path.split('/').slice('/')
              const apiName = pathSplit[pathSplit.length - 1]
              const fileName = pathSplit.length > 2 ? pathSplit[pathSplit.length - 2] : ''
              const mkdirPath = pathSplit.slice(0, pathSplit.length - 2).join('/') || '/'
              const fileApiSet = new Set()
              const filePath = Path.join(mkdirPath, fileName)
              if (!resultFile[filePath]) {
                resultFile[filePath] = fileTemplate
              }
              for (const method in paths[_path]) {
                const apiMeta = paths[_path][method]
                const parameters = apiMeta.parameters || []
                const formData = parameters.filter((item) => {
                  return item.in === 'formData'
                })
                const data = parameters.filter((item) => {
                  return item.in === 'body'
                })
                const params = parameters.filter((item) => {
                  return item.in === 'query'
                })
                resultFile[filePath] += functionCodeGener({
                  name: (() => {
                    const filterApiName = apiName.replace(/\.do$/g, '')
                    let result = Object.keys(paths[_path]).length > 1 ? `${method}_${filterApiName}` : filterApiName
                    if (fileApiSet.has(result)) {
                      let i = 1
                      while (fileApiSet.has(`${result}_${i}`)) {
                        i++
                      }
                      result = `${result}_${i}`
                    }
                    return result
                  })(),
                  method,
                  url: path,
                  comment: apiMeta.summary,
                  data,
                  params,
                  formData,
                  requestType: (() => {
                    if (method !== 'get') {
                      if (formData.length > 0) {
                        return 'formdata'
                      } else {
                        return 'json'
                      }
                    }
                  })()
                })
              }
            }
          }).catch((e) => {
            console.warn(`无法读取api文档: ${apiScope.name}`)
            console.warn(e.message)
          })
        })).then(() => {
          for (const path in resultFile) {
            mkdirsSync(Path.join(apiPath, path))
            const filepath = Path.join(apiPath, path, 'index.js')
            if (fs.existsSync(filepath) && fs.readFileSync(filepath).toString() !== resultFile[path]) {
              fs.writeFileSync(filepath, resultFile[path])
            }
          }
        })
      }).catch((e) => { })
    })
  }
}
