const system = require("../../../system");
const ServiceBase = require("../../svems.base");
const settings = require("../../../../config/settings");
const PROVINCE_CODE_MAP = require("../../../utils/province/province.js");
var moment = require('moment');
var Decimal = require('decimal.js');
class InvoiceService extends ServiceBase {
  constructor() {
    super();
    this.userSve = system.getObject("service.uc.userSve");
    this.businessmenSve = system.getObject("service.business.businessmenSve");
    this.INVOICE_TYPE = ["10","20","30"];
  }
  async processDics(params) {
    var rs = await this.callms("invoice", "processDics", params);
    return rs;
  }

  async invoiceApply(params) {
    var rs = await this.callms("invoice", "invoiceApply", params);
    return rs;
  }

  async invoicePage(params) {
    params.currentPage = Number(params.currentPage || 1);
    params.pageSize = Number(params.pageSize || 10);

    var rs = await this.callms("invoice", "invoicePage", params);
    if (rs.data && rs.data.rows) {
      for (let item of rs.data.rows) {
        item.invoice_amount = system.f2y(item.invoice_amount);
      }
    }
    return rs;
  }


  async deliverInvoicePage(params) {
    params.currentPage = Number(params.currentPage || 1);
    params.pageSize = Number(params.pageSize || 10);
    var rs = await this.callms("invoice", "deliverInvoicePage", params);
    if (rs.data && rs.data.rows) {
      for (let item of rs.data.rows) {
        item.invoice_amount = system.f2y(item.invoice_amount);
      }
    }
    return rs;
  }

  async handleStatus(params) {
    return await this.callms("invoice", "handleStatus", params);
  }

  async invoice(params) {
    var rs = await this.callms("invoice", "invoice", params);
    await this.setUcUser([rs.data]);
    return rs;
  }

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

    let ids = [];
    for (let row of rows) {
      if (row.bd_id) {
        ids.push(row.bd_id);
      }
      if (row.assign_user_id) {
        ids.push(row.assign_user_id);
      }
    }

    let userRs = await this.userSve.mapByIds({
      ids: ids
    });
    let userMap = userRs.data || {};

    for (let row of rows) {
      let user = userMap[row.bd_id] || {};
      row.bd_name = user.realName || "";

      let assignUser = userMap[row.assign_user_id] || {};
      row.assign_user_name = assignUser.realName || "";
    }
  }

  /**
   * fn:为了对接财务宝 格式化发票类型
   * 
   * @param {*} invoice_type 
   */
  formatInvoiceType(invoicesummaryinfo) {
    let _billType = null;
    if (!invoicesummaryinfo.invoice_type) {
      return system.getResult(null, `系统错误 发票类型错误`);
    }
    if (invoicesummaryinfo['invoice_type'] == '10') {
      _billType = `1`;
    } else if (invoicesummaryinfo['invoice_type'] == '20') {
      _billType = `2`;
    } else if (invoicesummaryinfo['invoice_type'] == '30') {
      _billType = `0`;
    } else {
      return system.getResult(null, `系统错误 发票类型错误`);
    }
    return _billType;
  }

  /**
   * fn:为了对接财务宝 格式化发票联次
   * 
   * @param {*} invoice_type 
   */
  formatInvoiceJoin(invoicesummaryinfo) {
    let invoiceOrder = null;
    if (!invoicesummaryinfo.invoice_join) {
      return system.getResult(null, `系统错误 发票联次错误`);
    }
    if (invoicesummaryinfo['invoice_join'] == '10') {
      invoiceOrder = `3`;
    } else if (invoicesummaryinfo['invoice_join'] == '20') {
      invoiceOrder = `0`;
    } else if (invoicesummaryinfo['invoice_join'] == '30') {
      invoiceOrder = `1`;
    } else if (invoicesummaryinfo['invoice_join'] == '40') {
      invoiceOrder = `2`;
    } else {
      return system.getResult(null, `系统错误 发票类型错误`);
    }
    return invoiceOrder;
  }

  /**
   * fn:为了对接财务宝 格式化发票摘要
   * @param {*} invoicesummaryinfo 
   */
  formatSummary(invoicesummaryinfo) {
    if (!invoicesummaryinfo.summary) {
      return system.getResult("系统错误 发票摘要信息错误");
    }
    let _res = [];
    for (let item of invoicesummaryinfo.summary) {
      // item = JSON.parse(item);
      let temp = {
        abstractMsg: item.summaryInfo,
        attr: {
          "standard": item.category,
          "unit": item.unit,
          "number": item.number,
          "unit_price": item.unitPrice
        },
        amount: item.amount,
        tax: item.taxAmount,
        totalPrice: Number(item.amount) + Number(item.taxAmount),
        taxRate: item.taxRate,
        abstractType: item.summaryType
      };
      _res.push(temp);
    }
    return _res;
  }
  /**
   * fn:提交发票道财税系统
   * @param {*} invoice_id 
   */
  async uploadDetail(invoice_id) {
    let invoice = await this.callms("invoice", "invoice", {
      id: invoice_id
    });
    if (!invoice || !invoice.data) {
      return system.getResult(`发票不存在`);
    }
    //获取个体户信息 拿到customer  在order服务下  参数：通过merchant_credit_code或者是merchant_id (购买方商户)
    if (!invoice.data.invoicesummaryinfo || !invoice.data.invoicesummaryinfo.businessmen_credit_code) {
      return system.getResult(`发票信息错误`);
    }
    let businessmen = await this.callms("order", "queryObusinessmenByCreditCode", {
      credit_code: invoice.data.invoicesummaryinfo.businessmen_credit_code
    });
    //获取交付商信息 拿到companyID  在common服务下 参数：通过deliver_id
    if (!invoice.data.deliver_id) {
      return system.getResult(`交付商不存在`);
    }
    var deliver = await this.callms("common", "deliverInfo", {
      id: invoice.data.deliver_id
    });
    if (!deliver.data) {
      return system.getResult(null, `交付商不存在`);
    }
    if (!deliver.data.nt_company_id) {
      return system.getResult(null, `个体户还未建账，请先建账`);
    }
    let _params = await this.buildParams(businessmen.data, invoice.data, deliver.data) || {};
    try {
      if (!_params) {
        console.log("推送失败，参数错误");
        return system.getResult("推送失败，参数错误");
      }
      let url = settings.ntapi().uploadDetail;
      let res = await this.callApi(url, _params, "提交发票");
      console.log(res);
      if (!res || res.code != '000000') {
        return system.getResult(null, "提交发票失败");
      }
      //更新发票建账
      await this.callms("invoice", "uploadDetail", {
        id: invoice_id
      });
      return system.getResultSuccess();
    } catch (error) {
      console.log(error);
      return system.getResult(null, `系统错误 推送失败`);
    }
  }
  // http://nga-api.gongsibao.com/nga-api/uploadDetail		
  /**
   * 推送票据
   */
  async buildParams(businessmen, invoice, deliver) {
    try {
      let _invoicesummaryinfo = invoice.invoicesummaryinfo || null;
      if (!_invoicesummaryinfo) {
        return system.getResult(null, `系统错误 发票信息错误`);
      }
      let params = {
        companyId: deliver.nt_company_id, //公司ID
        customerId: businessmen.customer_id, //客户ID
        uploadPeriod: moment(businessmen.create_account_time).format('YYYYMM'), //上传账期
        imageName: invoice['invoice_img'].slice(invoice['invoice_img'].lastIndexOf("/") + 1, -1) || "", //图片名称
        imageBasename: invoice['invoice_img'] || "", //图片url
        billType: this.formatInvoiceType(_invoicesummaryinfo), //发票类型
        isDaikai: `1`, //是否代开 1:yes  0:no                                                        
        signDate: moment(_invoicesummaryinfo.invoice_time).format("YYYY-MM-DD"), //开票时间
        invoiceCode: _invoicesummaryinfo.invoice_no, //发票代码
        invoiceNumber: _invoicesummaryinfo.invoice_number, //发票号码
        invoiceOrder: this.formatInvoiceJoin(_invoicesummaryinfo), //发票联次
        payName: _invoicesummaryinfo.merchant_name,
        receiveName: _invoicesummaryinfo.businessmen_name,
        payBank: _invoicesummaryinfo.merchant_bank,
        payAccount: _invoicesummaryinfo.merchant_account,
        payTel: _invoicesummaryinfo.merchant_mobile,
        payAddress: _invoicesummaryinfo.merchant_addr,
        payAccountAame: "", //xxxx
        payerTaxIdentificationNumber: _invoicesummaryinfo.merchant_credit_code,
        receiveBank: _invoicesummaryinfo.businessmen_bank,
        receiveAccount: _invoicesummaryinfo.businessmen_account,
        receiveTel: _invoicesummaryinfo.businessmen_mobile,
        receiveAddress: _invoicesummaryinfo.businessmen_addr,
        receiveTaxIdentificationNumber: _invoicesummaryinfo.businessmen_credit_code,
        // province: PROVINCE_CODE_MAP[_invoicesummaryinfo.province],
        province: _invoicesummaryinfo.province,
        receiveAccountName: "", //xxxx
        sourceClient: "0", //票据来源
        createDate: moment(_invoicesummaryinfo.created_at).format("YYYY-MM-DD HH:ss:mm"), //创建时间
        // createDate:new Date(_invoicesummaryinfo.created_at),    //创建时间
        list: this.formatSummary(_invoicesummaryinfo)
      }
      return params;
    } catch (error) {
      console.log(error);
      return {};
    }
  }

  /**
   * 发票试算
   * @param {*} params 
   * credit_code  ：统一社会信用代码
   */
  async calcInvoice(params) {
    if (!params.credit_code) {
      return system.getResult(null, `参数错误 统一社会信用代码不能为空`);
    }
    if(!this.INVOICE_TYPE.includes(this.trim(params.invoice_type))){
      return  system.getResult(null,  `参数错误，发票类型不存在`);
    }
    if(!this.trim(params.invoice_amount)){
      return  system.getResult(null,  `参数错误，发票金额非法`);
    }
    try {
      //取出个体工商户信息  
      var businessRes = await this.businessmenSve.queryObusinessmenByCreditCode({
        credit_code: this.trim(params.credit_code)
      });
      if (businessRes.status != 0 && !businessRes.data) {
        return system.getResult(null, `个体户不存在`);
      }
      let businessmenBean = businessRes.data;
      if (!businessmenBean.sign_time) {
        return system.getResult(null, `个体户未签约`);
      }
      params.invoice_amount = system.y2f(this.trim(params.invoice_amount));
      //增值税累计类型 1按月 2按季度    add_value_up_type
      //个税累计类型 1按月累计 2按季度累计  tax_up_type
      let accumulatedAmountParams = {
        add_value_up_type: businessmenBean.add_value_up_type,
        tax_up_type: businessmenBean.tax_up_type,
        credit_code: this.trim(params.credit_code),
        invoiced_time: this.trim(params.invoiced_time)
      };
      //取出累计开票金额
      var invoiceRes = await this.callms("invoice", "accumulatedAmount", accumulatedAmountParams);
      if (!invoiceRes || invoiceRes.status != 0 || !invoiceRes.data) {
        return system.getResult(null, `系统错误`);
      }
      let additional_tax_total = invoiceRes.data.addValueRes.additional_tax_total,    //附加税累计总和
        value_added_tax_total = invoiceRes.data.addValueRes.value_added_tax_total,    //增值税累计总和
        invoice_amount_total = new Decimal(invoiceRes.data.addValueRes.invoice_amount_total).plus(params.invoice_amount).toNumber();      //增值税累计价税总和  (计算不对)


      let personal_invoice_tax_total = invoiceRes.data.taxValueRes.personal_invoice_tax_total;  //个税累计总和
      let personal_invoice_amount_total = new Decimal(invoiceRes.data.taxValueRes.personal_invoice_amount_total).plus(params.invoice_amount).toNumber();  //个税价税累计总和 （计算不对）

      //**********************************************************一下是计算个税********************************************************************************************** */

      let apettemp = Decimal(1).plus(Decimal.div(businessmenBean.tax_rate,100)).toNumber();      //此参数 在计算附加税和增值税 复用
      //累计不含税价(个税)
      let accumulatedPriceExcludingTax = Decimal.div(personal_invoice_amount_total, apettemp).toNumber();

      let aptemp = new Decimal(1).sub(Decimal.div(businessmenBean.cost_rate,100)).toNumber();
      //累计利润
      let accumulatedProfit = new Decimal(accumulatedPriceExcludingTax).mul(aptemp).toNumber();

      //计算梯度的增值税附加税个税 的税率  {rate,qcd,zengzhiRate,fujiaRate}
      let rateRes = this.findTaxAndQCD(accumulatedProfit,params.invoice_type,businessmenBean);
      
      //个税 = 累计利润*个税税率-速算扣除数-该月/季度 累计缴纳的个税
      let personal_invoice_tax = new Decimal(accumulatedProfit).mul( rateRes.rate).sub(rateRes.qcd).sub(personal_invoice_tax_total).toNumber().toFixed(2);

      //***********************************************************一下是计算附加税和增值税******************************************************************************** */

      //累计不含税价(个税)
      let accumulatedPriceExcludingTax1 = Decimal.div(invoice_amount_total, apettemp).toNumber();
      //计算梯度的增值税附加税个税 的税率  {rate,qcd,zengzhiRate,fujiaRate}
      let AVRateRes = this.findTaxAndQCD(accumulatedPriceExcludingTax1,params.invoice_type,businessmenBean);
      //增值税税 = 累计不含税价*增值税-该月累计缴纳的增值税
      let value_added_tax = new Decimal(accumulatedPriceExcludingTax1).mul(AVRateRes.zengzhiRate).sub(value_added_tax_total).toNumber().toFixed(2);
      //附加税 =增值税*附加税
      let additional_tax = new Decimal(value_added_tax).mul(AVRateRes.fujiaRate).toNumber().toFixed(2);

      //************************************************************一下是计算服务费************************************* */
      let service_rate = new Decimal(businessmenBean.service_rate).div(100).toNumber();
      let service_amount = new Decimal(params.invoice_amount).mul(service_rate).toNumber();

      personal_invoice_tax = system.f2y(personal_invoice_tax);
      value_added_tax = system.f2y(value_added_tax);
      additional_tax = system.f2y(additional_tax);
      service_amount = system.f2y(service_amount);
      return system.getResult({personal_invoice_tax,value_added_tax,additional_tax,service_amount});
    } catch (error) {
      console.log(error);
      return system.getResult(null,`系统错误`);
    }
  }


  /**
   * 
   * 
   * 查询税率和速算扣除数
   * @param {*} invoice_amount 
   * @param {*} taxArguments 
   */
  findTaxAndQCD(invoice_amount,invoice_type,businessmenBean){
    let tax_ladder = null,other_ladder = null;
    if(invoice_type=="10"){ //专业发票
      tax_ladder = JSON.parse(businessmenBean.common_tax_ladder);
      other_ladder = JSON.parse(businessmenBean.common_ohter_ladder);
    } else{    //普通发票
      tax_ladder = JSON.parse(businessmenBean.special_tax_ladder);
      other_ladder = JSON.parse(businessmenBean.special_other_ladder);
    }

    let rate = 0, qcd = 0,zengzhiRate=0,fujiaRate = 0;
    for(let item of tax_ladder){  //计算个税的税率和速算扣除数
      if(item.minValue<= invoice_amount && item.maxValue>=invoice_amount){
        qcd = item.quicalDed || 0;
        rate = new Decimal(item.rate).div(100).toNumber() || 0;
      }
    } 
    for(let temp of other_ladder){//计算增/附加 税的税率和速算扣除数
      if(temp.minValue<= invoice_amount && temp.maxValue>=invoice_amount){
        zengzhiRate = new Decimal(temp.zengzhiRate).div(100).toNumber() || 0;
        fujiaRate = new Decimal(temp.fujiaRate).div(100).toNumber() || 0;
      }
    }
    return {rate,qcd,zengzhiRate,fujiaRate};
  }



}
module.exports = InvoiceService;