const system = require("../../../system");
const ServiceBase = require("../../svems.base");
const settings = require("../../../../config/settings");
const fs = require("fs");
const xlsx = require('node-xlsx');

class TradeService extends ServiceBase {
  constructor() {
    super();
    this.businessmenSve = system.getObject("service.business.businessmenSve");
    this.merchantSve = system.getObject("service.saas.merchantSve");
    this.redisClient = system.getObject("util.redisClient");
  }

  async orderPage(params) {
    params.currentPage = Number(params.currentPage || 1);
    params.pageSize = Number(params.pageSize || 10);
    let rs = await this.callms("trade", "orderPage", params) || {};
    if(rs.data && rs.data.rows) {
      this.transFields(rs.data.rows);
    }
    return rs;
  }

  async orderInfo(params) {
    let rs = await this.callms("trade", "orderInfo", params) || {};
    let order = rs.data;
    if(order) {
      this.transFields([order]);
      let merchant = await this.merchantSve.info({id: params.saas_merchant_id}) || {};
      merchant = merchant.data || {};
      order.merchant_name = merchant.name;
    }
    return rs;
  }

  async itemPage(params) {
    params.currentPage = Number(params.currentPage || 1);
    params.pageSize = Number(params.pageSize || 10);
    let rs = await this.callms("trade", "itemPage", params) || {};
    if(rs.data && rs.data.rows) {
      this.transFields(rs.data.rows);
    }
    return rs;
  }

  async lockOrder(params) {
    params.acc_type = this.trim(params.acc_type);
    params.fileUrl = this.trim(params.fileUrl);
    let itemList = params.itemList || [];
    if (["00", "01", "02"].indexOf(params.acc_type) == -1) {
      return system.getResultFail(-1, `请选择打款通道`, itemList);
    }

    if (itemList.length == 0) {
      return system.getResultFail(-1, `锁定批次无数据`, itemList);
    }
    // 验证字段
    let error = await this.checkItemList(itemList);
    if (error) {
      return system.getResultFail(-1, `批次内有错误数据，请检查后修改`, itemList);
    }
    // 获取商户签约信息
    let info = await this.merchantSve.signInfo({id: params.saas_merchant_id}) || {};
    info = info.data || {};
    let main = info.main || {};
    // 计算预计付款金额
    let result = await this.countAmt(itemList, info);

    for (let item of itemList) {
      item.amt = system.y2f(item.actual_amt);
      item.actual_amt = system.y2f(item.actual_amt);
      item.deduct_amt = system.y2f(item.deduct_amt);
      item.service_tax = system.y2f(item.service_tax);
    }

    let out_trade_no = await this.redisClient.genrateId("gsb_out_trade_no");
    // 构建订单对象
    let order = {
      saas_id: params.saas_id,
      saas_merchant_id: params.saas_merchant_id,
      out_trade_no: out_trade_no,
      service_rate: system.y2f(info.trans_service_rate),
      amt: system.y2f(result.actual_amt),
      actual_amt: system.y2f(result.actual_amt),
      deduct_amt: system.y2f(result.deduct_amt),
      service_tax: system.y2f(result.service_tax),
      item_count: itemList.length,
      acc_type: params.acc_type,
      order_file: params.fileUrl,
      // 付款凭证信息
      pay_voucher: "",
      pay_bank_account: main.bank_account,
      pay_bank_name: main.bank_name,
      pay_bank_no: main.bank_no,
      itemList: itemList
    };
    let rs = await this.callms("trade", "orderAdd", order);
    return rs;
  }

  async offlinePay(params) {
    params.type = "offline";
    params.pay_voucher = this.trim(params.pay_voucher);
    params.pay_bank_account = this.trim(params.pay_bank_account);
    params.pay_bank_name = this.trim(params.pay_bank_name);
    params.pay_bank_no = this.trim(params.pay_bank_no);
    if (!params.pay_voucher) {
      return system.getResult(null, "请上传凭证");
    }
    let rs = await this.callms("trade", "orderPay", params);
    return rs;
  }

  async parseItems(params) {
    // 读取excel
    let itemList = await this.readItems(params.fileUrl, params.fileName);

    // 验证字段
    let error = await this.checkItemList(itemList);

    // 获取商户签约信息
    let info = await this.merchantSve.signInfo({id: params.saas_merchant_id}) || {};

    // 计算预计付款基恩
    let result = await this.countAmt(itemList, (info.data || {}));

    // 封装返回对象
    result.error = error;
    result.itemList = itemList;
    return system.getResultSuccess(result);
  }

  async countAmt(itemList, info) {
    let result = {amt: 0, actual_amt: 0, deduct_amt: 0, service_tax: 0};
    if (!itemList) {
      return result;
    }

    // 服务费，这里已经处理了分转元，不用在处理
    let service_rate = info.trans_service_rate;

    // 计算金额
    for (let data of itemList) {
      let amt = Number(data.amt);
      data.service_tax = parseFloat((amt * service_rate) / 100).toFixed(2);
      data.actual_amt = parseFloat(amt).toFixed(2);
      data.deduct_amt = parseFloat(Number(data.actual_amt) + Number(data.service_tax)).toFixed(2);

      // 总服务费
      result.service_tax = Number(result.service_tax) + Number(data.service_tax);
      // 总实发
      result.actual_amt = Number(result.actual_amt) + Number(data.actual_amt);
      // 总请求打款
      result.amt = Number(result.amt) + amt;
    }
    // 总扣款
    result.deduct_amt = Number(result.service_tax) + Number(result.actual_amt);
    return result;
  }

  async readItems(fileUrl, fileName) {
    let itemList = [];
    let filePath = settings.localpath() + "saas_xgg_trade_order_" + this.trim(fileName) + ".xlsx";
    try {
      // await this.downloadFile(params.url, filePath);
      await this.restClient.execDownload2(fileUrl, filePath);

      let sheets = xlsx.parse(filePath);
      fs.unlinkSync(filePath);

      if (!sheets || sheets.length == 0) {
        return system.getResult(null, "打款文件无数据")
      }
      let sheet = sheets[0];
      if (!sheet || !sheet.data || sheet.data.length == 0) {
        return system.getResult(null, "打款文件无数据")
      }
      let rows = sheet.data;
      let itemList = [];
      for (let idx = 6; idx < rows.length; idx++) {
        var data = {
          errors: []
        };

        let cells = rows[idx];
        let cellLength = cells.length;

        if (cellLength == 0) {
          continue;
        }
        if (cellLength < 7) {
          data.errors.push("缺少数据, 列数不全");
          continue;
        }
        data.acc_name = this.trim(cells[1]);
        data.credit_code = this.trim(cells[2]).toUpperCase();
        data.acc_no = this.trim(cells[3]);
        data.open_bank = this.trim(cells[4]);
        data.amt = this.trim(cells[5]);
        data.remark = this.trim(cells[6]);
        itemList.push(data);
      }

      return itemList;
    } catch (error) {
      console.log(error);
      return system.getResult(null, "excel解析出错")
    }
  }

  async checkItemList(itemList) {
    let error = false;
    if (!itemList || itemList.length == 0) {
      return system.getResult(null, "打款文件无数据")
    }

    // 统一社会信用代码获取
    let creditCodes = [];
    for (let data of itemList) {
      creditCodes.push(data.credit_code);
    }
    let creditCodeMap = await this.businessmenSve.mapByCreditCodes({creditCodes: creditCodes, attrs: "credit_code"});
    for (let data of itemList) {
      this.checkField(data, "acc_name", {name: "收款户名", is_require: true, maxLen: 64});
      let bm = creditCodeMap[data.credit_code];
      if (!bm) {
        data.errors.push(`统一社会信用代码[${data.credit_code}]不存在`);
      }
      this.checkField(data, "credit_code", {name: "个体户统一信用代码", is_require: true, eqLen: 18});
      this.checkField(data, "acc_no", {name: "收款账号", is_require: true, maxLen: 30, is_number: true});
      this.checkField(data, "open_bank", {name: "开户银行全称", maxLen: 100});
      this.checkField(data, "amt", {name: "商户请求打款金额", is_require: true, maxLen: 100, is_number: true});
      this.checkField(data, "remark", {name: "备注", maxLen: 100});

      if (!error && data.errors.length > 0) {
        error = true;
      }
    }
    return error;
  }

  checkField(data, field, rule) {
    if (!data || !field) {
      return;
    }
    data.errors = data.errors || [];
    let v = data[field];
    if (rule.is_require && !v) {
      data.errors.push(`${rule.name}未填写`);
    }
    if (rule.maxLen && v.length > rule.maxLen) {
      data.errors.push(`${rule.name}长度不允许超过${rule.maxLen}`);
    }
    if (rule.minLen && v.length < rule.minLen) {
      data.errors.push(`${rule.name}长度不允许少于${rule.minLen}`);
    }
    if (rule.eqLen && v.length != rule.eqLen) {
      data.errors.push(`${rule.name}长度为${rule.eqLen}`);
    }
    if (rule.is_number && isNaN(v)) {
      data.errors.push(`${rule.name}需要填写数字类型`);
    }
    if (rule.is_number && isNaN(v)) {
      data.errors.push(`${rule.name}需要填写数字类型`);
    }
  }

  transFields(rows) {
    if(!rows || rows.length == 0) {
      return;
    }

    for(let row of rows) {
      row.amt = system.f2y(row.amt);
      row.actual_amt = system.f2y(row.actual_amt);
      row.deduct_amt = system.f2y(row.deduct_amt);
      row.service_tax = system.f2y(row.service_tax);
      row.service_rate = system.f2y(row.service_rate);
    }
  }
}

module.exports = TradeService;