#!/usr/bin/env node

const program = require('commander');
const minimist = require('minimist');
const chalk = require('chalk');
const packageMsg = require('./package.json');
const { createProject, createView, createApi } = require('./lib/choose');
const path = require('path');
const fs = require('fs');
const os = require('os');
const { spawnSync } = require('child_process');
const crypto = require('crypto');
const hash = crypto.createHash('md5');
const packageTemplate = require('./template/package_template');
let root = process.cwd(); // 当前命令执行目录
const { languageBagFileExt, languageInstallCommand } = require('./config/common');
const { copyFile, downloadGit, deleteFolderRecursive, getGerneratorInitData, copyDir, awaitMe} = require('./lib/helper');
const { defaultConfig } = require('./template/defaultConfig');
const { validatorConf } = require('./lib/validator');

const permissionUrl = 'https://gitee.com/tang_zi_han/generator-permission'
const phpTemplateUrl = 'https://gitee.com/tang_zi_han/generator-php-template.git'
const javaTemplateUrl = 'https://gitee.com/tang_zi_han/generator-java-template.git'
const pythonTemplateUrl = 'https://gitee.com/tang_zi_han/generator-python-template.git'
const viewUrl = 'https://gitee.com/tang_zi_han/generator-admin'
const uniAPPTemplate = 'https://gitee.com/tang_zi_han/generator-uniapp-template'
const clientUrl = 'https://gitee.com/tang_zi_han/generator-web-template.git'
const echartsTempalte = 'https://gitee.com/tang_zi_han/generator-echarts-template.git'
const viewVue3Url = `https://gitee.com/tang_zi_han/`

const _downloadServer = async (arg,root,name) => {
  if (arg.language != 'nodejs') {
    switch (arg.language) {
      case 'php':
        await downloadGit(phpTemplateUrl, root, `${name}-server`)
        break;
      case 'java':
        await downloadGit(javaTemplateUrl, root, `${name}-server`)
        break;
      case 'python':
        await downloadGit(pythonTemplateUrl, root, `${name}-server`)
        break;
      default:
        break;
    }
    // 删除本地git
    deleteFolderRecursive(`${root}/${name}-server/.git`)
  }
  console.log(`✨  Creating project in ${root}`);
  console.log(`✨ Initialize the project`)
}

program
  .command('app <app-name>')
  .description('Choose a development language')
  .action(async (name, cmd) => {
    console.log(chalk.bold.blue(`${packageMsg.name} ${packageMsg.version}`))
    if (minimist(process.argv.slice(3))._.length > 1) {
      console.log(chalk.yellow('\n Warning: You provided more than one argument. The first one will be used as the app\'s name, the rest are ignored.'))
    }
    // 选择参数
    const arg = await createProject();
    arg.name = name
    // 主服务根目录
    arg.projectName = name;
    root = path.resolve(root, `./${name}`);
    // 创建项目
    fs.mkdirSync(root, { recursive: true });
    // 创建基础模型配置文件
    fs.mkdirSync(`${root}/modelConf`, { recursive: true });
    // 创建系统模型示例文件 系统模型不会生成代码
    await copyFile(path.join(__dirname, './template/model/system/uc_permission_model.js'), `${root}/modelConf/uc_permission_model.js`);
    await copyFile(path.join(__dirname, './template/model/system/uc_role_model.js'), `${root}/modelConf/uc_role_model.js`);
    await copyFile(path.join(__dirname, './template/model/system/uc_role_per_model.js'), `${root}/modelConf/uc_role_per_model.js`);
    await copyFile(path.join(__dirname, './template/model/system/uc_route_model.js'), `${root}/modelConf/uc_route_model.js`);
    await copyFile(path.join(__dirname, './template/model/system/uc_user_model.js'), `${root}/modelConf/uc_user_model.js`);
    // 数据库默认配置


    // copy 系统说明文件
    await copyFile(path.join(__dirname, `./document/${arg.language}/项目目录结构.txt`), `${root}/项目目录结构.txt`);
    await copyFile(path.join(__dirname, `./document/${arg.language}/项目启动.docx`), `${root}/项目目录结构.docx`);
    // 创建项目配置文件
    fs.writeFile(`${root}/cli.config.js`, defaultConfig(arg), (err) => {
      if (err) throw err;
    });

   await _downloadServer(arg, root, name)

    // 生成 node端权限认证中间商 client => node(permission) => java/php  , java/php => node(permission) => client
    const permissionFolder = arg.language == 'nodejs' ? `${name}-server` : `${name}-permission`
    await downloadGit(permissionUrl, root, permissionFolder, 'noredis-master')
    // 引入语言包 生成 api 
    console.log(`use [ generator-${arg.language}-bag ] helper...`)

    // 前提必须安装 对应语言包 npm i generator-nodejs-bag -g
    const languageBag = require(`generator-${arg.language}-bag`)
    // 生成api
    const gerneratorInitData = getGerneratorInitData(root, arg)
    languageBag.gernerateApi(gerneratorInitData)
    // 进入权限包执行 npm install
    const installCmdName = os.platform().startsWith('win') ? 'npm.cmd' : 'npm';
    spawnSync(installCmdName, ['install'], { cwd: `${root}/${permissionFolder}`, stdio: 'inherit' });
    // 删除本地git
    deleteFolderRecursive(`${root}/${permissionFolder}/.git`)
    // 自动执行项目初始化文件
    // spawnSync('node', [ 'init' ], { cwd: `${root}/${permissionFolder}`, stdio: 'inherit' });

    /**
     * ====================================非nodejs处理==============================
     */

    console.log("✨  Creating project success")
    console.log('@ Get started with the following commands:')
    console.log(`@ Manually create a database, then run 【/${name}/${permissionFolder}/permission.sql】`)
    console.log(chalk.blue(`     $ cd ${name}/${permissionFolder}`))
    console.log(chalk.blue(`     $ npm run env:dev`))
    /**
     * ====================================非nodejs处理end==============================
     */
  })
// 生成默认的模型配置文件
program
  .command('make:model')
  .description('Make a model')
  .option('-m, --m [type]', 'Select a model to generate curd')
  .option('-like, --like [like]', 'Select a model to generate curd')
  .action(async (name, cmd) => {
    let model = name.m
    let likeModel = name.like
    if (!model) throw new Error('必须指定某个模型 如 generator make:model -m user')
    let modelFile = path.join(__dirname, './template/model/defaultModelConfig.js')
    if (likeModel) {
      modelFile = path.join(__dirname, `./template/model/${likeModel}_model.js`)
      console.log("mosw",modelFile )
    }
    copyFile(modelFile, `${root}/modelConf/${model}_model.js`)
    console.log(chalk.blue(`success! ${root}/modelConf/${model}_model.js`))
  })
// 生成 根据模型生成curd,默认全部模型
program
  .command('make:api')
  .description('Make curd')
  .option('-m, --m [type]', 'Select a model to generate curd')
  .action(async (name, cmd) => {
    // 选择参数
    const createArg = await createApi();
    if (createArg.isSure == 'no') return;

    let model = name.m || ''
  
    // 验证用户编写的配置文件是否符合规范
    console.log(chalk.yellow(`Generating API for 【${model || 'allModels'}】 please wait...`))
    const arg = require(path.join(`${root}`, './cli.config.js'))
    if (!validatorConf(root, model, arg)) {
      console.log(chalk.red("Verification failed. Please rewrite the configuration file"))
      return;
    } else {
      console.log(chalk.blue("✨ Validation successful,0 errors"))
    }
    // const hasStr = hash.update(new Date().getTime().toString());
    // fs.mkdir(`${root}/${arg.projectName}-${viewAfterFix}/.cli`, { recursive: true }, (err) => {
    //   copyDir(`${root}/${arg.projectName}-${viewAfterFix}`, `${root}/${arg.projectName}-${viewAfterFix}/.cli/${hasStr.digest('hex')}`,['node_modules','.cli','.git'])
    // });
    // 没有server文件夹默认第一次创建，需要下载远程代码
    if (!fs.existsSync(`${root}/${arg.projectName}-server`)) {
      await _downloadServer(arg, root, `${root}/${arg.projectName}`)
    }
    // 引入语言包 生成 api 
    console.log(`✨ use [ generator-${arg.language}-bag ] helper...`)
    // 前提必须安装 对应语言包 npm i generator-nodejs-bag -g
    const languageBag = require(`generator-${arg.language}-bag`)
    // 生成api
    const gerneratorInitData = getGerneratorInitData(root, arg, model)
    languageBag.gernerateApi(gerneratorInitData)
    console.log(chalk.blue(`✨ Generating API for 【${model || 'allModels'}】 success!`))


  })

// 根据模型生成 管理视图 默认全部模型    
program
  .command('make:view')
  .description('Make view')
  .option('-m, --m [type]', 'Select a model to generate curd')
  .action(async (name, cmd) => {

    let model = name.m
    const arg = require(path.join(`${root}`, './cli.config.js'))
    console.log(chalk.yellow(`Generating View for 【${model || 'allModels'}】 please wait...`))


    if (!validatorConf(root, model, arg)) {
      console.log(chalk.red("Verification failed. Please rewrite the configuration file"))
      return;
    } else {
      console.log(chalk.blue("✨ Validation successful,0 errors"))
    }
   await  awaitMe(500)
    const viewAfterFix = 'view'
    // 没有视图文件夹默认第一次创建，需要下载远程代码
    if (!fs.existsSync(`${root}/${arg.projectName}-${viewAfterFix}`)) {
      // 选择参数
      const createArg = await createView();
      arg.template = createArg.template
      fs.writeFile(`${root}/cli.config.js`,defaultConfig(arg), (err) => {
        if (err) throw err;
      });
      if (createArg.isSure == 'no') {
        return;
      }

      await downloadGit(viewVue3Url+createArg.template+'.git', root, `${root}/${arg.projectName}-${viewAfterFix}`, 'master') // master_pro
      // 删除本地git
      deleteFolderRecursive(`${root}/${arg.projectName}-${viewAfterFix}/.git`)
    }
    // 备份之前的代码到.cli文件夹里面
    const hasStr = hash.update(new Date().getTime().toString());
    fs.mkdir(`${root}/${arg.projectName}-${viewAfterFix}/.cli`, { recursive: true }, (err) => {
      copyDir(`${root}/${arg.projectName}-${viewAfterFix}`, `${root}/${arg.projectName}-${viewAfterFix}/.cli/${hasStr.digest('hex')}`,['node_modules','.cli','.git'])
    });
    await awaitMe(5000)
    let generateView = require('app-generator-view-vue3')
    const gerneratorInitData = getGerneratorInitData(root, arg, model)
    generateView(gerneratorInitData,arg)
    console.log(chalk.blue(`✨ Generating View for 【${model || 'allModels'}】 success!`))
   
  })

// 根据模型生成word文档    
program
  .command('make:document')
  .description('Make document')
  .option('-m, --m [type]', 'select document type e.g:word,pptx,excel')
  .action(async (name, cmd) => {
    let type = name.m
    const arg = require(path.join(`${root}`, './cli.config.js'))
    let { autoWord, autoPPT } = require('generator-autoword')
    try {
      switch (type) {
        case 'pptx':
          autoPPT(root, arg)
          break;
        case 'word':
          autoWord(root, arg)
          break;
        default:
          break;
      }
    } catch (error) {
      console.log("error",error)
    }
  })

// 根据模型生成uni-app api
program
  .command('make:uniAppApi')
  .description('Make document')
  .option('-m, --m [type]', 'Select a model to generate uniAppApi')
  .action(async (name, cmd) => {
    let model = name.m || ''
    const arg = require(path.join(`${root}`, './cli.config.js'))
    console.log(chalk.yellow(`Generating uniAppApi for 【${model || 'allModels'}】 please wait...`))
    const generatorUniappBag = require(`generator-uniapp-bag`)
    const appFolder = `${arg.projectName}-app`
    // 没有uniapp项目默认第一次创建，需要下载远程代码
    if (!fs.existsSync(`${root}/${appFolder}`)) {
      await downloadGit(uniAPPTemplate, root, `${root}/${appFolder}`, 'master')
      // 删除本地git
      deleteFolderRecursive(`${root}/${appFolder}/.git`)
    }
    // 生成api
    // 指定模型代表已经初始化过一次了，直接生成视图即可
    const gerneratorInitData = getGerneratorInitData(root, arg, model)
    generatorUniappBag.gernerateApi(gerneratorInitData)
    console.log(chalk.blue(`✨ Generating uniAppApi for 【${model || 'allModels'}】 success!`))
  })

  program
  .command('make:client')
  .description('make pc web')
  .action(async (name, cmd) => {
    const arg = require(path.join(`${root}`, './cli.config.js'))
    const appFolder = `${arg.projectName}-client`
    // 没有uniapp项目默认第一次创建，需要下载远程代码
    if (!fs.existsSync(`${root}/${appFolder}`)) {
      await downloadGit(clientUrl, root, `${root}/${appFolder}`, 'master')
      // 删除本地git
      deleteFolderRecursive(`${root}/${appFolder}/.git`)
    }
  })

  

// 生成数据大屏
program
  .command('make:screen')
  .description('make a screen')
  .action(async (name, cmd) => {
    const arg = require(path.join(`${root}`, './cli.config.js'))
    const generatorEchartsBag = require(`generator-echarts-bag`)
    // 第一次拉取echarts模板
    const appFolder = `${root}/${arg.projectName}-screen`
    if (!fs.existsSync(appFolder)) {
      await downloadGit(echartsTempalte, root, appFolder, 'master')
      // 删除本地git
      deleteFolderRecursive(`${appFolder}/.git`)
    }
    const gerneratorInitData = getGerneratorInitData(root, arg)
    generatorEchartsBag.gernerateScreen(gerneratorInitData)
    console.log(chalk.blue(`✨ Generating Screen Success！`))
  })



async function makePackage(name, arg, serverRoot) {
  return new Promise(resolve => {
    const content = packageTemplate(name, arg)
    fs.writeFile(`${root}/${serverRoot}/${languageBagFileExt[arg.language]}`, content, (err) => {
      if (err) throw err;
      resolve();
    });
  })
}

program.parse(process.argv);


