const system = require("../../../system")
const settings = require("../../../../config/settings")
const CtlBase = require("../../ctlms.base");
const validation = system.getObject("util.validation");
const moment = require("moment");
const axios = require("axios");

class InvoiceCtl extends CtlBase {
  constructor() {
    super();
    this.orderSve = system.getObject("service.saas.orderSve");
    this.tradeSve = system.getObject("service.trade.tradeSve");
    this.invoiceSve = system.getObject("service.saas.invoiceSve");
    this.merchantSve = system.getObject("service.saas.merchantSve");

    this.redisClient = system.getObject("util.redisClient");
  }

  // 注册订单列表
  async orderPage(params, pobj2, req) {
    try {
      params.unInvoice = 1;
      params.handle_statuses = ['20', '30'];
      this.doTimeCondition(params, ["createBegin", "createEnd"]);
      return await this.orderSve.page(params);
    } catch (error) {
      return system.getResult(null, `系统错误 错误信息 ${error}`);
    }
  }

  // 交易信息列表页
  async tradePage(params, pobj2, req) {
    try {
      params.unInvoice = 1;
      params.order_type = params.fee_type;
      params.trade_status = "00";
      this.doTimeCondition(params, ["createBegin", "createEnd"]);
      return await this.tradeSve.itemPage(params);
    } catch (error) {
      return system.getResult(null, `系统错误 错误信息 ${error}`);
    }
  }

  // 交易列表
  async platformPage(params, pobj2, req) {
    try {
      if (["00", "10", "20"].indexOf(params.fee_type) == -1) {
        return system.getResultSuccess({count: 0, rows: [], fee_type: params.fee_type});
      }
      if (params.fee_type == "00") {
        return this.orderPage(params, pobj2, req);
      } else {
        return this.tradePage(params, pobj2, req);
      }
    } catch (error) {
      return system.getResult(null, `系统错误 错误信息 ${error}`);
    }
  }

  //发票列表
  async invoicePage(params, pobj2, req) {
    try {
      let rs = await this.invoiceSve.merchantinvoicePage(params);
      return rs;
    } catch (error) {
      return system.getResult(null, `系统错误 错误信息 ${error}`);
    }
  }

  // 发票申请
  async apply(params, pobj2, req) {
    try {
      validation.check(params, "fee_type", {name: "费用记录类型", is_require: true, dics: ['00', "10", "20"]});
      let fee_type = this.trim(params.fee_type);
      if (fee_type == "00") {
        return await this.apply00(params, pobj2, req);
      } else if (fee_type == "10") {
        return await this.apply10(params, pobj2, req);
      } else if (fee_type == "20") {
        return await this.apply20(params, pobj2, req);
      } else {
        return system.getResult(null, "费用类型错误");
      }
    } catch (error) {
      let msg = error.message;
      if (msg.startsWith("bpo-validation-error:")) {
        return system.getResult(null, msg.replace("bpo-validation-error:", ""));
      }
      return system.getResult(null, `系统错误 错误信息 ${error}`);
    }
  }

  // 功能2开票(平台交易)
  async apply10(params, pobj2, req) {
    validation.check(params, 'data_ids', {name: "交易信息", arr_require: true});

    let title = await this.merchantSve.title(params) || {};
    title = title.data || {};
    if (!title.merchant_name || !title.merchant_credit_code || !title.merchant_addr
      || !title.merchant_mobile || !title.merchant_bank || !title.merchant_account) {
      return system.getResult(null, "开票抬头不完整，请联系平台");
    }

    let addr = await this.merchantSve.addr(params) || {};
    addr = addr.data || {};
    if (!addr || !addr.mail_to || !addr.mail_addr || !addr.mail_mobile) {
      return system.getResult(null, "开票邮寄不完整");
    }

    let trades = await this.tradeSve.byIds({
      ids: params.data_ids,
      saas_merchant_id: params.saas_merchant_id,
      attrs: "id",
      trade_statuses: ['00'],
      unInvoice: true,
    }) || [];
    if (trades.data.length != params.data_ids.length) {
      return system.getResult(null, "交易数据选择有误，请重新搜索后选择");
    }

    let info = await this.merchantSve.signInfo({id: params.saas_merchant_id}) || {};
    info = info.data || {};
    if (!info.main_invoice || !info.main_invoice.id) {
      return system.getResult(null, "商户未设置开票签约主体，请联系平台进行设置、");
    }
    let main = info.main_invoice || {};
    let batch_no = await this.redisClient.genrateId("invoice_batch_no");
    let apply_no = await this.redisClient.genrateId("invoice_apply_no");
    let data = {
      saas_id: params.saas_id,
      saas_merchant_id: params.saas_merchant_id,
      parent_id: "",
      owner_type: "00",
      status: "1000",
      batch_no: batch_no,
      apply_no: apply_no,
      fee_type: this.trim(params.fee_type),
      invoice_type: this.trim(params.invoice_type),

      from_name: main.name,
      from_credit_code: main.credit_code,
      from_mobile: main.mobile,
      from_addr: main.addr,
      from_bank: main.bank_name,
      from_account: main.bank_account,

      to_name: this.trim(title.merchant_name),
      to_credit_code: this.trim(title.merchant_credit_code),
      to_addr: this.trim(title.merchant_addr),
      to_mobile: this.trim(title.merchant_mobile),
      to_bank: this.trim(title.merchant_bank),
      to_account: this.trim(title.merchant_account),

      mail_addr: this.trim(addr.mail_addr),
      mail_mobile: this.trim(addr.mail_mobile),
      mail_to: this.trim(addr.mail_to),
      data_ids: params.data_ids.join(","),
    };

    data = await this.invoiceSve.applySave(data);
    console.log(data);
    data = data.data;
    if (!data || !data.id) {
      return system.getResult(null, "网络异常，发票申请失败");
    }

    let rs = await this.tradeSve.updateInvoice({ids: params.data_ids, saas_invoice_id: data.id});
    console.log(rs);

    console.log(data);
    return system.getResultSuccess(data);
  }

  // 功能1开票（商户交易  也是线下交易）
  async apply20(params, pobj2, req) {
    try {
      validation.check(params, "invoice_type", {name: "发票类型", is_require: true, dics: ['30', "10", "20"]});
      validation.check(params, "pay_voucher", {name: "支付凭证", is_require: true});
      validation.check(params, "invoiceList", {name: "开票信息", arr_require: true});

      let title = await this.merchantSve.title(params) || {};
      title = title.data || {};
      if (!title.merchant_name || !title.merchant_credit_code || !title.merchant_addr
        || !title.merchant_mobile || !title.merchant_bank || !title.merchant_account) {
        return system.getResult(null, "开票抬头不完整，请联系平台");
      }

      let addr = await this.merchantSve.addr(params) || {};
      addr = addr.data || {};
      if (!addr || !addr.mail_to || !addr.mail_addr || !addr.mail_mobile) {
        return system.getResult(null, "开票邮寄不完整");
      }

      let info = await this.merchantSve.signInfo({id: params.saas_merchant_id}) || {};
      info = info.data || {};
      // TODO WK
      if (!info.main_invoice) {
        return system.getResult(null, "商户未设置开票签约主体，请联系平台进行设置、");
      }
      let main = info.main_invoice;
      let invoiceList = params.invoiceList;

      let creditCodes = [];
      for (let invoice of invoiceList) {
        creditCodes.push(invoice.credit_code);
      }
      let businessmenMap = await this.orderSve.mapByCreditCodes({
        creditCodes: creditCodes,
        saas_merchant_id: params.saas_merchant_id
      });

      for (let invoice of invoiceList) {
        validation.check(businessmenMap, invoice.credit_code, {name: `个体户[${invoice.credit_code}]`, is_require: true});
      }

      let applyList = [];
      let pay_amount = 0;
      let batch_no = await this.redisClient.genrateId("invoice_batch_no");
      for (let invoice of invoiceList) {
        if (!invoice.data_ids) {
          return system.getResult(null, "数据有变化，请刷新重试");
        }

        let bussinessmen = businessmenMap[invoice.credit_code];
        let apply_no = await this.redisClient.genrateId("invoice_apply_no");
        let data = {
          saas_id: params.saas_id,
          saas_merchant_id: params.saas_merchant_id,
          parent_id: "",
          owner_type: "00",
          status: "1000",
          batch_no: batch_no,
          apply_no: apply_no,
          fee_type: params.fee_type,
          invoice_amount: system.y2f(invoice.invoice_amount),
          invoice_type: this.trim(params.invoice_type),

          from_name: bussinessmen.name,
          from_credit_code: bussinessmen.credit_code,
          from_mobile: bussinessmen.legal_mobile,
          from_addr: bussinessmen.business_place,
          from_bank: bussinessmen.bank_name,
          from_account: bussinessmen.bank_no,

          to_name: this.trim(main.name),
          to_credit_code: this.trim(main.credit_code),
          to_mobile: this.trim(main.mobile),
          to_addr: this.trim(main.addr),
          to_bank: this.trim(main.bank_name),
          to_account: this.trim(main.bank_no),

          mail_addr: this.trim(addr.mail_addr),
          mail_mobile: this.trim(addr.mail_mobile),
          mail_to: this.trim(addr.mail_to),

          personal_invoice_tax: system.y2f(invoice.personal_invoice_tax),
          additional_tax: system.y2f(invoice.additional_tax),
          service_tax: system.y2f(invoice.service_tax),
          value_added_tax: system.y2f(invoice.value_added_tax),
          unit: this.trim(invoice.unit),
          quantity: this.trim(invoice.quantity),
          price: this.trim(invoice.price),
          remark: this.trim(invoice.remark),
          pay_voucher: this.trim(params.pay_voucher),
          data_ids: invoice.data_ids,
        };
        pay_amount = pay_amount + Number(data.personal_invoice_tax || 0) + Number(data.additional_tax || 0) + Number(data.value_added_tax || 0) + Number(data.service_tax || 0);
        applyList.push(data);
      }

      let signInfo = await this.merchantSve.signInfo({id: params.saas_merchant_id});
      if (!signInfo || !signInfo.data) {
        return system.getResult(null, "商户签约信息不存在，请先做签约配置");
      }

      let accountInfo = JSON.stringify({
        name: this.trim(main.name),
        credit_code: this.trim(main.credit_code),
        bank_account: this.trim(main.bank_account),
        bank_name: this.trim(main.bank_name),
        bank_no: this.trim(main.bank_no),
        addr: this.trim(main.addr),
        mobile: this.trim(main.mobile)
      });
      // 支付信息
      let pay = await this.tradeSve.saveStPay({
        saas_id: params.saas_id,
        saas_merchant_id: params.saas_merchant_id,
        pay_voucher_img: params.pay_voucher,
        trade_no: batch_no,
        busi_name: "saas_invoice_apply.batch_no",
        busi_id: batch_no,
        amount: pay_amount,
        pay_type: "1",
        pay_status: "10",
        account_info: accountInfo,
      });
      // 判断支付是否插入
      if (!pay || pay.status != 0 || !pay.data) {
        return system.getResult(null, "");
      }

      let rs = await this.invoiceSve.applyBulkSave({
        fee_type: params.fee_type,
        dataList: applyList,
        parent_id: ""
      });
      if (rs && rs.data && rs.data.length > 0) {
        // 更改支付状态
        await this.tradeSve.updatePayStatus({
          id: pay.data.id,
          pay_status: "20",
        });
        for (let d of rs.data) {
          console.log(d.id, d.data_ids);
          if (!d.data_ids) {
            continue;
          }
          let tradeIds = d.data_ids.split(",");
          await this.tradeSve.updateInvoice({ids: tradeIds, saas_invoice_id: d.id});
        }
      }
      return system.getResultSuccess(rs);
    } catch (error) {
      let msg = error.message;
      if (msg.startsWith("bpo-validation-error:")) {
        return system.getResult(null, msg.replace("bpo-validation-error:", ""));
      }
      return system.getResult(null, `系统错误 错误信息 ${error}`);
    }
  }

  // 功能3开票（订单交易）
  async apply00(params, pobj2, req) {
    validation.check(params, 'data_ids', {name: "订单信息", arr_require: true});

    let title = await this.merchantSve.title(params) || {};
    title = title.data || {};
    if (!title.merchant_name || !title.merchant_credit_code || !title.merchant_addr
      || !title.merchant_mobile || !title.merchant_bank || !title.merchant_account) {
      return system.getResult(null, "开票抬头不完整，请联系平台");
    }

    let addr = await this.merchantSve.addr(params) || {};
    addr = addr.data || {};
    if (!addr || !addr.mail_to || !addr.mail_addr || !addr.mail_mobile) {
      return system.getResult(null, "开票邮寄不完整");
    }

    let orders = await this.orderSve.byIds({
      ids: params.data_ids,
      saas_merchant_id: params.saas_merchant_id,
      attrs: "id,price",
      handle_status: ['20', '30'],
      unInvoice: true,
    }) || [];
    if (orders.data.length != params.data_ids.length) {
      return system.getResult(null, "订单数据选择有误，请重新搜索后选择");
    }
    let invoice_amount = 0;
    for (let item of orders.data) {
      invoice_amount = invoice_amount + Number(item.price || 0);
    }

    let info = await this.merchantSve.signInfo({id: params.saas_merchant_id}) || {};
    // service_tax
    info = info.data || {};
    if (!info.main_invoice) {
      return system.getResult(null, "商户未设置开票签约主体，请联系平台进行设置、");
    }
    let main = info.main_invoice || {};
    let batch_no = await this.redisClient.genrateId("invoice_batch_no");
    let apply_no = batch_no;
    let service_tax = parseFloat((Number(invoice_amount) * Number(info.invoice_service_rate) / 100).toFixed(2));
    let data = {
      saas_id: params.saas_id,
      saas_merchant_id: params.saas_merchant_id,
      parent_id: "",
      owner_type: "00",
      status: "1000",
      batch_no: batch_no,
      apply_no: apply_no,
      fee_type: this.trim(params.fee_type),
      invoice_type: this.trim(params.invoice_type),

      from_name: main.name,
      from_credit_code: main.credit_code,
      from_mobile: main.mobile,
      from_addr: main.addr,
      from_bank: main.bank_name,
      from_account: main.bank_account,

      to_name: this.trim(title.merchant_name),
      to_credit_code: this.trim(title.merchant_credit_code),
      to_addr: this.trim(title.merchant_addr),
      to_mobile: this.trim(title.merchant_mobile),
      to_bank: this.trim(title.merchant_bank),
      to_account: this.trim(title.merchant_account),

      mail_addr: this.trim(addr.mail_addr),
      mail_mobile: this.trim(addr.mail_mobile),
      mail_to: this.trim(addr.mail_to),

      invoice_amount: invoice_amount,
      service_tax: service_tax,
      data_ids: params.data_ids.join(","),
    };

    data = await this.invoiceSve.applySave(data);
    console.log(data);
    data = data.data;
    if (!data || !data.id) {
      return system.getResult(null, "网络异常，发票申请失败");
    }

    let rs = await this.orderSve.updateInvoice({ids: params.data_ids, saas_invoice_id: data.id});
    console.log(rs);

    console.log(data);
    return system.getResultSuccess(data);
  }

  //发票申请列表
  async merchantinvoiceapplyPage(params, pobj2, req) {
    try {
      params.currentPage = Number(params.currentPage || 1);
      params.pageSize = Number(params.pageSize || 1);
      let rs = await this.invoiceSve.merchantinvoiceapplyPage(params);
      return rs;
    } catch (error) {
      return system.getResult(null, `系统错误 错误信息 ${error}`);
    }
  }

  /**
   * 发票账单列表
   * @param {*} params
   * @param {*} pobj2
   * @param {*} req
   */
  async invoiceOrder(params, pobj2, req) {
    if (!params.id) {
      return system.getResult(null, `发票ID 不能为空`);
    }
    try {
      return await this.invoiceSve.invoiceOrder(params);
    } catch (error) {
      console.log(error);
      return system.getResult(null, `系统错误`);
    }
  }

  // 功能1 确定个体户开票
  async confirmInvoice(params, pobj2, req) {
    try {
      if (params.fee_type != "20") {
        system.getResult(null, "费用类型错误");
      }
      let invoiceData = await this.buildTradeInvoice(params);
      return invoiceData;
    } catch (error) {
      console.log(error);
      let msg = error.message;
      if (msg.startsWith("bpo-validation-error:")) {
        return system.getResult(null, msg.replace("bpo-validation-error:", ""));
      }
      return system.getResult(null, `系统错误`);
    }
  }

  async buildTradeInvoice(params) {
    validation.check(params, 'data_ids', {name: "交易信息", arr_require: true});
    let invoice_type = params.invoice_type;
    // 查交易
    let items = await this.tradeSve.byIds({
      ids: params.data_ids,
      saas_merchant_id: params.saas_merchant_id,
      order_type: params.fee_type,
      trade_statuses: ['00'],
      unInvoice: true,
    }) || [];
    items = items.data;
    if (!items || params.data_ids.length != items.length) {
      return system.getResult(null, "交易信息有变化，请刷新重新选择");
    }
    let signInfo = await this.merchantSve.signInfo({id: params.saas_merchant_id});
    if (!signInfo || !signInfo.data) {
      return system.getResult(null, "商户签约信息不存在，请先做签约配置");
    }

    // 开票签约主体
    let main = signInfo.data.main_invoice;
    if (!main || !main.id) {
      return system.getResult(null, "开票签约主体未设置，请联系平台配置");
    }

    let invoice_service_rate = signInfo.data.invoice_service_rate || 0;

    let bmMap = {};
    let creditCodes = [];
    for (let item of items) {
      let creditCode = item.credit_code;
      let list = bmMap[creditCode] || [];
      list.push(item);
      bmMap[creditCode] = list;
      creditCodes.push(creditCode);
    }
    let businessmenMap = await this.orderSve.mapByCreditCodes({
      creditCodes: creditCodes,
      saas_merchant_id: params.saas_merchant_id
    });

    let invoiceList = [];
    let calcParams = [];

    for (let creditCode in bmMap) {
      let businessmen = businessmenMap[creditCode];
      let itemList = bmMap[creditCode];
      let amount = 0;
      let data_ids = [];
      for (let item of itemList) {
        amount = amount + Number(item.amt || 0);
        data_ids.push(item.id);
      }
      let service_tax = parseFloat((Number(amount) * Number(invoice_service_rate) / 100).toFixed(2));
      if (!businessmen.is_bank) {
        calcParams.push({
          "credit_code": creditCode,
          "invoiced_time": moment().format("YYYY-MM-DD hh:mm:ss"),
          "invoice_type": invoice_type,
          "invoice_amount": amount
        });
      }

      // TODO 总统计算 end
      invoiceList.push({
        "name": businessmen.name,
        "credit_code": creditCode,
        "is_bank": businessmen.is_bank ? 1 : 0,
        "is_bank_name": businessmen.is_bank ? "已开户" : "未开户",
        "invoice_amount": system.f2y(amount),
        "personal_invoice_tax": 0,
        "additional_tax": 0,
        "value_added_tax": 0,
        "service_tax": system.f2y(service_tax),
        "unit": "",
        "quantity": "",
        "price": "",
        "remark": "",
        "data_ids": data_ids.join(","),
      });
    }

    let additional_tax_total = 0;
    let personal_invoice_tax_total = 0;
    let value_added_tax_total = 0;
    let service_tax_total = 0;
    let pay_total = 0;

    // TODO 总统计算 begin
    // 计算税金
    try {
      let calcMap = {};
      if (calcParams.length > 0) {
        let url = settings.deliverSysApi().calcInvoice;
        let res = await axios({
          method: 'post',
          url: url,
          data: calcParams
        });
        if (!res || !res.data || res.data.status != 0 || res.data.data.length == 0) {
          return system.getResult(null, `试算错误`);
        }

        let calcList = res.data.data;
        let errors = [];
        for (let c of calcList) {
          calcMap[c.credit_code] = c;
          if (c.error) {
            errors.push(`${c.msg}【${c.credit_code}】`);
          }
        }

        if (errors.length > 0) {
          return system.getResult(null, errors.join("、"));
        }
      }

      for (let invoice of invoiceList) {
        let businessmen = businessmenMap[invoice.credit_code];
        if (!businessmen.is_bank) {
          let invoiceCalc = calcMap[invoice.credit_code];
          additional_tax_total = additional_tax_total + Number(invoiceCalc.additional_tax);
          personal_invoice_tax_total = personal_invoice_tax_total + Number(invoiceCalc.personal_invoice_tax);
          value_added_tax_total = value_added_tax_total + Number(invoiceCalc.value_added_tax);

          invoice.personal_invoice_tax = system.toFloat(Number(invoiceCalc.personal_invoice_tax));
          invoice.additional_tax = system.toFloat(Number(invoiceCalc.additional_tax));
          invoice.value_added_tax = system.toFloat(Number(invoiceCalc.value_added_tax));
        }

        pay_total = pay_total + system.toFloat(Number(invoice.personal_invoice_tax || 0) + Number(invoice.additional_tax || 0) + Number(invoice.value_added_tax || 0) + Number(invoice.service_tax || 0));
        service_tax_total = service_tax_total + Number(invoice.service_tax);
      }

      return system.getResultSuccess({
        tax: {
          additional_tax_total: system.toFloat(additional_tax_total),
          personal_invoice_tax_total: system.toFloat(personal_invoice_tax_total),
          value_added_tax_total: system.toFloat(value_added_tax_total),
          service_tax_total: system.toFloat(service_tax_total),
          pay_total: system.toFloat(pay_total),
        },
        main: main,
        invoiceList: invoiceList
      });
    } catch (error) {
      console.log(error);
      return system.getResult(null, `系统错误`);
    }
  }
}

module.exports = InvoiceCtl;
