// 修改所有后台接口路径为ui开头

const argv = require('yargs').argv._
const babylon = require('babylon')
const fs = require('fs')
const path = require('path')
const t = require('@babel/types')
const generate = require('@babel/generator').default
const traverse = require('@babel/traverse').default

let fileDir = argv[0] || '../src/' || './test'


/**
 * 字符串操作类，在调用replace时不会真正的替换，而只是记录要替换的位置，在调用toString时才进行替换，并返回替换后的新的字符串
 */
class StringEditor {
  constructor(content, start, end) {
    this.content = content
    this.start = start || 0
    this.end = end || content.lengt
    this.stack = []
  }

  /**
   * 记录要替换的字符的位置和新字符串
   */
  replace(start, end, newString) {
    this.stack.push({
      range: [start, end],
      newString: newString
    })
    return this.stack.length - 1
  }
  /**
   * 同String.prototype.slice
   */
  slice(start, end) {
    return this.content.slice(start, end)
  }
  /**
   * 完成字符串替换并返回结果
   */
  toString() {
    var value = ''
    var start = this.start
    this.stack = this.stack.sort(function (a, b) {
      return a.range[0] - b.range[0]
    })
    for (var i = this.stack.length - 1; i >= 0; i--) {
      // 删除掉被其他range包含的range
      var action = this.stack[i]
      var prevAction = this.stack[i - 1]
      if (
        prevAction &&
        action.range[0] >= prevAction.range[0] &&
        action.range[1] <= prevAction.range[1]
      ) {
        this.stack.splice(i, 1)
      }
    }
    for (i = 0; i < this.stack.length; i++) {
      action = this.stack[i]
      value += this.content.substring(start, action.range[0])
      value += action.newString.toString()
      start = action.range[1]
    }

    value += this.content.substring(start, this.end)
    return value
  }
}


if (fileDir.charAt(1) !== ':') {
  fileDir = path.join(__dirname, fileDir)
}
let fileRegx = /^.(js|vue)$/
const logs = {};
traveller(fileDir)
console.log(logs)
fs.writeFileSync(path.join(__dirname,new Date().toTimeString().replace(/:| .+/g,'')+'.json'), JSON.stringify(logs));

function traveller(fileDir) {
  if (fs.existsSync(fileDir)) {
    let files = fs.readdirSync(fileDir)
    files.forEach(fileName => {
      let filePath = path.join(fileDir, fileName)
      let file = fs.statSync(filePath)
      let ext = path.extname(fileName)
      if (file.isDirectory()) {
        traveller(filePath)
      } else if (ext.match(fileRegx)) {
        let fileContent = fs.readFileSync(filePath, 'utf-8')
        let jsContent = fileContent
        if (ext === '.vue') {
          fileContent = fileContent.split(/<\/?script[^>]*>/)
          jsContent = (fileContent[1]||'')
        }
        if(jsContent.trim().length){
          const source = new StringEditor(jsContent)
          console.log('=> ',filePath)
          let ast = babylon.parse(jsContent, { 
            sourceType: 'module',
            // 注意babylon的plugins和babel的plugins不是一回事
            plugins:[
              "jsx",
              'dynamicImport',
              'classProperties',
              'objectRestSpread'
            ]
          })
          alterEndPath(ast, source, filePath, logs)
          if(source.stack.length){
            let transFileContent = source.toString()
            if(ext === '.vue'){
              transFileContent = fileContent[0]+'<script>'+transFileContent+'</script>'+fileContent[2]
            }
            // console.log(transFileContent)
            fs.writeFileSync(filePath, transFileContent);
          }
        }
      }
    })

  }
}

function alterEndPath(ast, source, filePath,logs) {
  traverse(ast, {
    CallExpression: function(path){
      let node = path.node;
      // axios 之后的都替换
      if(node.callee.object && node.callee.object.name === 'axios'){
        let apiPath
        let origPath
        let arg0 = node.arguments[0]

        if(arg0.type=='StringLiteral' && arg0.value && /^\/?\w+/.test(arg0.value) && ! arg0.value.startsWith('http://') && !/^\/?(ui|assets|lib)\//.test(arg0.value)){
          apiPath = arg0.value
        }
        if(arg0.type=='BinaryExpression' && arg0.left.type=='StringLiteral' && arg0.left.value && /^\/?\w+/.test(arg0.left.value) && ! arg0.left.value.startsWith('http://') && !/^\/?(ui|assets|lib)\//.test(arg0.left.value)){
          apiPath = arg0.left.value
        }
        if(arg0.type=='TemplateLiteral' && arg0.quasis[0].value && /^\/?\w+/.test(arg0.quasis[0].value.raw) && ! arg0.quasis[0].value.raw.startsWith('http://') && !/^\/?(ui|assets|lib)\//.test(arg0.quasis[0].value.raw)){
          apiPath = arg0.quasis[0].value.raw
        }
        if(apiPath){
          if(apiPath[0]!=='/'){
            apiPath='/'+apiPath
          }
          origPath = apiPath.split('?')[0].replace(/\/$/,'')
          if(apiPath.startsWith('/api/')){
            apiPath = apiPath.replace('/api/','/ui/')
          }else{
            apiPath = '/ui'+apiPath
          }
          if(arg0.type=='StringLiteral'){
            logs[origPath]=apiPath.split('?')[0].replace(/\/$/,'')
            source.replace(
              arg0.start+1,
              arg0.end-1,
              apiPath
            )
          }else if(arg0.type=='BinaryExpression' && arg0.left.type=='StringLiteral'){
            logs[origPath]=apiPath.split('?')[0].replace(/\/$/,'')
            source.replace(
              arg0.left.start+1,
              arg0.left.end-1,
              apiPath
            )
          }else if(arg0.type=='TemplateLiteral'){
            logs[origPath]=apiPath.split('?')[0].replace(/\/$/,'')
            source.replace(
              arg0.quasis[0].start,
              arg0.quasis[0].end,
              apiPath
            )
          }
        }
      }
    },
    StringLiteral: function(path){
      const node = path.node;
      const parent = path.parent
      if(parent.type === 'CallExpression' && parent.callee.property && parent.callee.property.name === 'push'){
        return
      }
      if(parent.type === 'ObjectProperty' && parent.key.name === 'path'){
        return
      }
      // /api/ 开头 或三层以上的路径 ///
      if(node.value && /^(\/\w+){3}|^\/?api\/\w+/.test(node.value) && ! node.value.startsWith('@') && !/^\/?(ui|assets|lib)\//.test(node.value)){
          let origPath
          let apiPath = node.value
          if(apiPath[0]!=='/'){
            apiPath='/'+apiPath
          }
          origPath = apiPath.split('?')[0].replace(/\/$/,'')
          if(apiPath.startsWith('/api/')){
            apiPath = apiPath.replace('/api/','/ui/')
          }else{
            apiPath = '/ui'+apiPath
          }
          logs[origPath]=apiPath.split('?')[0].replace(/\/$/,'')
          source.replace(
            node.start+1,
            node.end-1,
            apiPath
          )
      }
    },
    TemplateElement: function(path){
      const node = path.node;
      const parent = path.parent
      if(parent.type === 'CallExpression' && parent.callee.property && parent.callee.property.name === 'push'){
        return
      }
      if(parent.type === 'ObjectProperty' && parent.key.name === 'path'){
        return
      }
      // /api/ 开头 或三层以上的路径 ///
      if(node.value && /^(\/\w+){3}|^\/?api\/\w+/.test(node.value.raw) && ! node.value.raw.startsWith('@') && !/^\/?(ui|assets|lib)\//.test(node.value.raw)){
          let origPath
          let apiPath = node.value.raw
          if(apiPath[0]!=='/'){
            apiPath='/'+apiPath
          }
          origPath = apiPath.split('?')[0].replace(/\/$/,'')
          if(apiPath.startsWith('/api/')){
            apiPath = apiPath.replace('/api/','/ui/')
          }else{
            apiPath = '/ui'+apiPath
          }
          logs[origPath]=apiPath.split('?')[0].replace(/\/$/,'')
          source.replace(
            node.start,
            node.end,
            apiPath
          )
      }
    }
  })

}
/* 最后还要替换 data-read-url="/api/faces"
补充
/ui/mediaaccounts/
/ui/avatar/
/ui/contentcore/resource/download
/ui/pageweaver/css


*/