package com.dxhy.erp.service.impl;

import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dxhy.common.constant.DbConstant;
import com.dxhy.common.constant.UserConstant;
import com.dxhy.common.datasource.config.DynamicContextHolder;
import com.dxhy.common.enums.ReturnCodeEnum;
import com.dxhy.common.util.pojo.Authorize;
import com.dxhy.common.util.pojo.GlobalInfo;
import com.dxhy.erp.dao.SysDeptDao;
import com.dxhy.erp.dao.SysUserDao;
import com.dxhy.erp.dao.SysUserOrgDao;
import com.dxhy.erp.dao.SysUserRoleDao;
import com.dxhy.erp.dao.TdxInvoiceDao;
import com.dxhy.erp.dao.TdxRecordInvoiceDao;
import com.dxhy.erp.entity.InvoiceElectron;
import com.dxhy.erp.entity.SysDeptEntity;
import com.dxhy.erp.entity.SysUserEntity;
import com.dxhy.erp.entity.SysUserOrgEntity;
import com.dxhy.erp.entity.SysUserRoleEntity;
import com.dxhy.erp.entity.TdxRecordInvoice;
import com.dxhy.erp.model.InvoiceScanEntity;
import com.dxhy.erp.model.ReturnStateInfo;
import com.dxhy.erp.model.TdxInvoiceAccount;
import com.dxhy.erp.model.TdxInvoiceInfo;
import com.dxhy.erp.model.UserInformation;
import com.dxhy.erp.service.IYaBaoService;
import com.fasterxml.jackson.databind.ObjectMapper;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64;
import lombok.extern.slf4j.Slf4j;

/**
 * @author JiangHuiTao
 * @date 2021/3/1
 */
@Slf4j
@Service
public class YaBaoServiceImpl implements IYaBaoService {

    @Resource
    private TdxRecordInvoiceDao tdxRecordInvoiceDao;

    @Resource
    private SysUserDao sysUserDao;

    @Resource
    private SysDeptDao sysDeptDao;

    @Resource
    private SysUserRoleDao sysUserRoleDao;

    @Resource
    private SysUserOrgDao sysUserOrgDao;

    @Resource
    private TdxInvoiceDao tdxInvoiceDao;

    @Value("${yb.orgid}")
    private Integer orgid;

    @Override
    public String getBx(GlobalInfo globalInfo, Map<String, String> requestParam,
        HttpServletRequest request, HttpServletResponse response, Authorize authorize) throws IOException {
        ReturnStateInfo run = new ReturnStateInfo();
        TdxInvoiceInfo data = JSON.parseObject(requestParam.get("data"), TdxInvoiceInfo.class);
        List<TdxInvoiceAccount> invoiceAccounts = data.getInvoices();// 报销信息参数集合
        Integer totalRow = data.getTotalRows();
        int total = invoiceAccounts.size();

        boolean flag = getCheck(invoiceAccounts);
        if (!flag || null == totalRow) {
            run.setReturnCode(ReturnCodeEnum.QQBWGSCW.getFhzDm());
            run.setReturnMessage(ReturnCodeEnum.QQBWGSCW.getFhzMc(ReturnCodeEnum.QQBWGSCW.getIndex()));
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");
            return "{ \"returnStateInfo\":" + JSON.toJSONString(run) + "}";
        }

        if (totalRow != total) { // 发票数量和总数量不一致 返回错误信息
            run.setReturnCode(ReturnCodeEnum.FPBYZ.getFhzDm());
            run.setReturnMessage(ReturnCodeEnum.FPBYZ.getFhzMc(ReturnCodeEnum.FPBYZ.getIndex()));
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");
            return "{ \"returnStateInfo\":" + JSON.toJSONString(run) + "}";
        }

        DynamicContextHolder.push("business" + DbConstant.BUSINESS_READ);
        getBxDetail(invoiceAccounts);

        run.setReturnCode(ReturnCodeEnum.CLCG.getFhzDm());
        run.setReturnMessage(ReturnCodeEnum.CLCG.getFhzMc(ReturnCodeEnum.CLCG.getIndex()));
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        return "{ \"returnStateInfo\":" + JSON.toJSONString(run) + "}";
    }

    @Transactional
    public void getBxDetail(List<TdxInvoiceAccount> invoiceAccounts) {
        for (TdxInvoiceAccount invoice : invoiceAccounts) {
            invoice.setIsSign("0");
            String invoiceCode = invoice.getInvoiceCode();
            String invoiceNo = invoice.getInvoiceNo();
            String invoiceDate = invoice.getInvoiceDate();
            invoiceDate = invoiceDate.replaceAll("-", "");
            if (invoiceDate.length() > 6) {
                String kprq =
                    invoiceDate.substring(0, 4) + "-" + invoiceDate.substring(4, 6) + "-" + invoiceDate.substring(6);
                invoice.setInvoiceDate(kprq);

            }
            String uuid = invoiceCode + invoiceNo;
            invoice.setUuid(uuid);
            TdxRecordInvoice tDxRecordInvoice = tdxRecordInvoiceDao.getRecordInvoiceByUuid(uuid);
            TdxInvoiceAccount tDxInvoiceAccount = tdxRecordInvoiceDao.getInvoiceAccount(uuid);
            InvoiceScanEntity invoiceScan = tdxRecordInvoiceDao.getInvoice(uuid);

            if (null != tDxRecordInvoice) { // 抵账存在，修改抵账签收状态
                tDxRecordInvoice.setVoucherNumber(invoice.getPzh());
                tDxRecordInvoice.setQsStatus("1");
                tDxRecordInvoice.setQsType("4");
                DynamicContextHolder.push("business" + DbConstant.BUSINESS_READ);
                tdxRecordInvoiceDao.updateRecordInvoice(tDxRecordInvoice, tDxRecordInvoice.getUuid());
                invoice.setIsSign("1");// 签收标志

                InvoiceScanEntity newInvoiceScan = new InvoiceScanEntity();
                newInvoiceScan.setGfName(tDxRecordInvoice.getGfName());
                newInvoiceScan.setGfTaxNo(tDxRecordInvoice.getGfTaxNo());
                newInvoiceScan.setXfName(tDxRecordInvoice.getXfName());
                newInvoiceScan.setXfTaxNo(tDxRecordInvoice.getXfTaxNo());
                newInvoiceScan.setInvoiceCode(invoiceCode);
                newInvoiceScan.setInvoiceNo(invoiceNo);
                newInvoiceScan.setUuId(uuid);
                newInvoiceScan.setInvoiceDate(invoiceDate);
                BigDecimal amount = tDxRecordInvoice.getInvoiceAmount();
                newInvoiceScan.setInvoiceAmount(amount == null ? "" : amount.toPlainString());
                newInvoiceScan.setTaxAmount(
                    tDxRecordInvoice.getTaxAmount() == null ? "" : tDxRecordInvoice.getTaxAmount().toPlainString());
                newInvoiceScan.setTotalAmount(
                    tDxRecordInvoice.getTotalAmount() == null ? "" : tDxRecordInvoice.getTotalAmount().toPlainString());
                newInvoiceScan.setQsStatus("1");
                newInvoiceScan.setQsType("4");
                newInvoiceScan.setNotes("签收成功");
                newInvoiceScan.setUserAccount(invoice.getBxr());
                newInvoiceScan.setUserName(invoice.getBxr());
                newInvoiceScan.setCheckCode(invoice.getCheckCode());
                newInvoiceScan.setInvoiceType(tDxRecordInvoice.getInvoiceType());
                InvoiceElectron tDxInvoiceEntity = new InvoiceElectron();
                BeanUtil.copyProperties(newInvoiceScan, tDxInvoiceEntity);
                tDxInvoiceEntity.setUuid(uuid);
                if (null == invoiceScan) {
                    tDxInvoiceEntity.setCreateDate(new Date());
                    tdxInvoiceDao.insert(tDxInvoiceEntity);
                } else {
                    tdxRecordInvoiceDao.updateInvoiceScan(newInvoiceScan);
                }
            }

            if (null != tDxInvoiceAccount) {
                tdxRecordInvoiceDao.updateInvoiceAccount(invoice);// 修改报销数据
            } else {
                tdxRecordInvoiceDao.saveInvoiceAccount(invoice);// 保存报销数据
            }

        }
    }

    @Override
    @Transactional
    public String yaBaoUserAdd(GlobalInfo globalInfo, Map<String, String> requestParam,
        HttpServletRequest request, HttpServletResponse response, Authorize authorize) {
        ReturnStateInfo run;
        List<UserInformation> data;
        String userInfo = requestParam.get("data");
        data = JSONObject.parseArray(userInfo, UserInformation.class);

        run = getUserInformationCheck(data);
        if (run.getReturnCode() != null || run.getReturnMessage() != null) {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");
            return "{\"globalInfo\":" + JSON.toJSONString(globalInfo) + ",\"returnStateInfo\":" + JSON.toJSONString(run)
                + "}";
        }
        for (UserInformation user : data) {
            SysUserEntity entity = new SysUserEntity();
            BeanUtil.copyProperties(user, entity);
            entity.setDeptId(orgid.longValue());
            String salt = RandomStringUtils.randomAlphanumeric(20);
            entity.setSalt(salt);
            entity.setPlpassword(Base64.encode(user.getPassword()));
            entity.setPassword(new BCryptPasswordEncoder(UserConstant.PW_ENCORDER_SALT).encode(user.getPassword()));
            SysDeptEntity sysDeptEntity = sysDeptDao.selectById(orgid);
            entity.setMobile(user.getPhoneNumber());
            entity.setCompany(sysDeptEntity.getCompany());
            entity.setStatus("1");
            // 增加用户
            sysUserDao.insert(entity);
            Long userid = entity.getUserId();
            // 增加用户角色关联
            SysUserRoleEntity userRoleEntity = new SysUserRoleEntity();
            userRoleEntity.setRoleId(user.getRoleNumber().longValue());
            userRoleEntity.setUserId(userid);
            sysUserRoleDao.insert(userRoleEntity);
            List<SysDeptEntity> list = sysDeptDao.selectByCompany(sysDeptEntity.getCompany());
            for (SysDeptEntity dept : list) {
                SysUserOrgEntity orgEntity = new SysUserOrgEntity();
                orgEntity.setCompany(dept.getCompany());
                orgEntity.setDeptId(orgid.longValue());
                orgEntity.setTaxname(dept.getTaxname());
                orgEntity.setTaxno(dept.getTaxno());
                orgEntity.setUserid(userid);
                sysUserOrgDao.insert(orgEntity);
            }
        }
        run.setReturnCode("0000");
        run.setReturnMessage("处理成功");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        return "{\"globalInfo\":" + JSON.toJSONString(globalInfo) + ",\"returnStateInfo\":" + JSON.toJSONString(run)
            + "}";
    }

    private boolean getCheck(List<TdxInvoiceAccount> list) {
        for (TdxInvoiceAccount entity : list) {
            String invoiceCode = entity.getInvoiceCode();
            String invoiceNo = entity.getInvoiceNo();
            String gfTaxNo = entity.getGfTaxNo();
            String xfTaxNo = entity.getXfTaxNo();
            String invoiceDate = entity.getInvoiceDate();
            String pzh = entity.getPzh();
            BigDecimal invoiceAmount = entity.getInvoiceAmount();
            String bxr = entity.getBxr();
            if (StringUtils.isBlank(invoiceCode) || StringUtils.isBlank(invoiceNo) || StringUtils.isBlank(gfTaxNo)
                || StringUtils.isBlank(xfTaxNo) || StringUtils.isBlank(invoiceDate) || null == invoiceAmount
                || StringUtils.isBlank(pzh) || StringUtils.isBlank(bxr)) {
                return false;
            }
        }
        return true;
    }

    private ReturnStateInfo getUserInformationCheck(List<UserInformation> data) {
        ReturnStateInfo run = new ReturnStateInfo();
        for (UserInformation userInfo : data) {
            String userName = userInfo.getUsername();
            String loginname = userInfo.getLoginname();
            String password = userInfo.getPhoneNumber();
            if (StringUtils.isEmpty(userName)) {
                run.setReturnCode("1001");
                run.setReturnMessage("用户名不可为空");
                return run;
            }
            if (StringUtils.isEmpty(loginname)) {
                run.setReturnCode("1002");
                run.setReturnMessage("登录名不可为空");
                return run;
            }
            if (StringUtils.isEmpty(userInfo.getPassword())) {
                run.setReturnCode("1002");
                run.setReturnMessage("密码不能为空");
                return run;
            }
            if (userInfo.getRoleNumber() == null) {
                run.setReturnCode("1002");
                run.setReturnMessage("RoleNumber不能为空");
                return run;
            }
            int user = sysUserDao.getUserByLoginName(loginname);
            if (user > 0) {
                run.setReturnCode("1004");
                run.setReturnMessage("登录名：" + loginname + " 已存在");
                return run;
            }
            if (StringUtils.isEmpty(password)) {
                run.setReturnCode("1003");
                run.setReturnMessage("密码不可为空");
                return run;
            }
        }
        return run;
    }

    private static String md5Encode(String password) {
        char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        try {
            byte[] btInput = password.getBytes(StandardCharsets.UTF_8);
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            mdInst.update(btInput);
            // 获得密文
            byte[] md = mdInst.digest();
            // 把密文转换成十六进制的字符串形式
            int j = md.length;
            char[] str = new char[j * 2];
            int k = 0;
            for (byte byte0 : md) {
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            log.error("{} 加密失败。", password, e);
            return null;
        }
    }
}
