package cn.superdesk.uniorder.service.invoice.impl;

import cn.superdesk.libs.common.json.JsonUtils;
import cn.superdesk.uniorder.common.ResponseResult;
import cn.superdesk.uniorder.common.enums.ExceptionMsg;
import cn.superdesk.uniorder.common.exception.SuperdeskUniOrderException;
import cn.superdesk.uniorder.dao.entity.accounting.unified.customer.AccountingUnifiedCustomer;
import cn.superdesk.uniorder.dao.entity.invoice.customer.InvoiceApply;
import cn.superdesk.uniorder.dao.entity.invoice.customer.InvoiceApplyExample;
import cn.superdesk.uniorder.dao.entity.invoice.customer.InvoiceOrder;
import cn.superdesk.uniorder.dao.entity.invoice.customer.InvoiceOrderExample;
import cn.superdesk.uniorder.dao.entity.order.ExpressCompany;
import cn.superdesk.uniorder.dao.entity.sys.SysConfig;
import cn.superdesk.uniorder.dao.mapper.accounting.unified.customer.AccountingUnifiedCustomerMapper;
import cn.superdesk.uniorder.dao.mapper.accounting.unified.customer.AccountingUnifiedCustomerMapperEx;
import cn.superdesk.uniorder.dao.mapper.accounting.unified.customer.AccountingUnifiedCustomerOrderGoodsMapper;
import cn.superdesk.uniorder.dao.mapper.accounting.unified.customer.AccountingUnifiedCustomerOrderGoodsMapperEx;
import cn.superdesk.uniorder.dao.mapper.invoice.customer.*;
import cn.superdesk.uniorder.dao.mapper.order.ExpressCompanyMapper;
import cn.superdesk.uniorder.dao.mapper.sys.SysConfigMapper;
import cn.superdesk.uniorder.dto.param.invoice.InvoiceApplyOrderGoodsParams;
import cn.superdesk.uniorder.dto.vo.accounting.unified.customer.ViewDzOrder;
import cn.superdesk.uniorder.dto.vo.invoice.*;
import cn.superdesk.uniorder.service.invoice.InvoiceApplyService;
import cn.superdesk.uniorder.utils.BeanUtils;
import cn.superdesk.uniorder.utils.DateHelper;
import cn.superdesk.uniorder.utils.JwtUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class InvoiceApplyCustomerServiceImpl implements InvoiceApplyService {


	@Autowired
	InvoiceApplyMapper          invoiceApplyMapper;
	@Autowired
	InvoiceApplyMapperEx        invoiceApplyMapperEx;
	@Autowired
	InvoiceApplyMapperExScore   invoiceApplyMapperExScore;
	@Autowired
	InvoiceApplyMapperExUnified invoiceApplyMapperExUnified;


	@Autowired
	InvoiceOrderMapper   invoiceOrderMapper;
	@Autowired
	InvoiceOrderMapperEx invoiceOrderMapperEx;

	@Autowired
	AccountingUnifiedCustomerMapper           accountingUnifiedCustomerMapper;
	@Autowired
	AccountingUnifiedCustomerOrderGoodsMapper accountingUnifiedCustomerOrderGoodsMapper;

	@Autowired
	AccountingUnifiedCustomerMapperEx           accountingUnifiedCustomerMapperEx;
	@Autowired
	AccountingUnifiedCustomerOrderGoodsMapperEx accountingUnifiedCustomerOrderGoodsMapperEx;

	@Autowired
	SysConfigMapper sysConfigMapper;


	@Autowired
	ExpressCompanyMapper expressCompanyMapper;

	@Override
	public List<InvoiceApplySelectVo> invoiceApplySelectFocusUnified(Map<String, Object> params) throws SuperdeskUniOrderException {
		return invoiceApplyMapperExUnified.invoiceApplySelectFocusUnified(params);
	}

	@Override
	public List<InvoiceApplySelectVo> invoiceApplySelectFocusScore(Map<String, Object> params) throws SuperdeskUniOrderException {
		return invoiceApplyMapperExScore.invoiceApplySelectFocusScore(params);
	}


	@Override
	@Transactional
	public void invoiceApply(String token, Map<String, Object> params) throws SuperdeskUniOrderException {

		String userId = JwtUtil.checkToken(token);

		// 判断商品Id
//		String orderGoodsIdStr = params.get("orderGoodIds").toString();
//		if (StringUtils.isBlank(orderGoodsIdStr)) {
//			throw new SuperdeskUniOrderException(ExceptionMsg.GOODIDS_NOT_EMPTY);
//		}

		// uog.id
//		String[] orderGoodsIds = orderGoodsIdStr.split(",");
//		if (orderGoodsIds == null || orderGoodsIds.length == 0) {
//			throw new SuperdeskUniOrderException(ExceptionMsg.GOODIDS_NOT_EMPTY);
//		}

//		List<Long> orderGoodsIdList = arrToListRemoval(orderGoodsIds);


		List<InvoiceApplyOrderGoodsParams> applyOrderGoodsParamsList = JsonUtils.toList(params.get("orderGoodsObj"), InvoiceApplyOrderGoodsParams.class);


		InvoiceApply invoiceApply = new InvoiceApply();

		Map<String, Object> codeMap = GetConfigByINVA();

		// 生成 发票申请SN
		invoiceApply.setInvoiceNo(codeMap.get("sn").toString());

		invoiceApply.setInvoiceTitle(params.get("invoiceCompanyName").toString());
		invoiceApply.setInvoiceType(Integer.valueOf(params.get("invoiceType").toString()));

		invoiceApply.setTaxRate(params.get("taxRate").toString());
		invoiceApply.setFreeAmount(new BigDecimal(params.get("freeAmount").toString()));
		invoiceApply.setRealAmount(new BigDecimal(params.get("realAmount").toString()));

		invoiceApply.setNoCheckCount(new BigDecimal(params.get("realAmount").toString()));
		invoiceApply.setRemark(params.get("remark").toString());

		invoiceApply.setApplyUserId(Long.valueOf(userId));
		invoiceApply.setApplyTime(DateHelper.getNow());

		invoiceApplyMapper.insertSelective(invoiceApply);


		for (Long goodsId : orderGoodsIdList) {


			// 获取 对账Id 和 订单Id 根据 goodId
			List<DzInvoiceOrderVo> dzInvoiceOrderVOList = accountingUnifiedCustomerOrderGoodsMapperEx.selectDzByGoodId(goodsId);

			if (dzInvoiceOrderVOList != null && dzInvoiceOrderVOList.size() > 0) {

				DzInvoiceOrderVo dzInvoiceOrderVO = dzInvoiceOrderVOList.get(0);

				InvoiceOrder invoiceOrder = new InvoiceOrder();

				// 获取刚刚insert的Id
				invoiceOrder.setInvoiceApplyId(invoiceApply.getId());
				// unified_order_goods.id 非传过来的goodsId 是系统自增生成的 Id
				invoiceOrder.setDzGoodId(goodsId);
				// accounting_unified_customer_order.id 中间表的 订单Id
				invoiceOrder.setDzOrderId(dzInvoiceOrderVO.getDzOrderId());
				// accounting_unified_customer.id
				invoiceOrder.setDzId(dzInvoiceOrderVO.getDzId());

				invoiceOrderMapper.insertSelective(invoiceOrder);

				// 用于查找是 全部开票 还是 部分开票的问题
				Integer invoiceStatus = invoiceApplyMapperEx.findStatusBydzId(dzInvoiceOrderVO.getDzId());


				/** ----------------------------------------- 更新 对账单 开票状态 ----------------------------------------- **/

				// TODO 要做 差异
				// 现在 这个是 一般订单的 对账单 结算单
				AccountingUnifiedCustomer dzMain = new AccountingUnifiedCustomer();
				dzMain.setId(dzInvoiceOrderVO.getDzId());
				dzMain.setInvoiceStatus(invoiceStatus);
				accountingUnifiedCustomerMapper.updateByPrimaryKeySelective(dzMain);

				/** ----------------------------------------- 更新 对账单 开票状态 ----------------------------------------- **/
			}
		}

		// 更新账单号
		SysConfig snconfig = new SysConfig();
		snconfig.setCode(codeMap.get("key").toString());
		snconfig.setValueDate(new Date((Long) (codeMap.get("valueDate"))));
		snconfig.setValueInt(Integer.parseInt(codeMap.get("valueInt").toString()));

		sysConfigMapper.updateByPrimaryKeySelective(snconfig);
	}

	@Override
	public ResponseResult<List<InvoiceApplyPage>> findViewByPage(Map<String, Object> params, int pageNum, int pageSize) throws SuperdeskUniOrderException {

		PageHelper.startPage(pageNum, pageSize);

		List<InvoiceApplyPage> ls = invoiceApplyMapperEx.selectByCondition(params);

		PageInfo<InvoiceApplyPage> page = new PageInfo<InvoiceApplyPage>(ls);
		PageHelper.clearPage();
		return new ResponseResult<List<InvoiceApplyPage>>(page.getPageNum(), page.getPageSize(), (int) page.getTotal(), ls);
	}

	@Override
	public InvoiceApplyDataVo findViewData(Map<String, Object> params) throws SuperdeskUniOrderException {
		return invoiceApplyMapperEx.findViewData(params);
	}

	@Override
	@Transactional
	public void check(String token, Map<String, Object> params) throws SuperdeskUniOrderException {

		String userId = JwtUtil.checkToken(token);

		InvoiceApply invoiceApply = new InvoiceApply();

		invoiceApply.setId(Long.valueOf(params.get("id").toString()));
		invoiceApply.setAuditUserId(Long.valueOf(userId));
		invoiceApply.setAuditTime(DateHelper.getNow());
		invoiceApply.setAuditStatus(Integer.valueOf(params.get("auditStatus").toString()));

		invoiceApplyMapper.updateByPrimaryKeySelective(invoiceApply);

		// TODO 写死
		if (params.get("auditStatus").toString().equals("3")) {

			InvoiceOrderExample          example  = new InvoiceOrderExample();
			InvoiceOrderExample.Criteria criteria = example.createCriteria();
			criteria.andInvoiceApplyIdEqualTo(Long.valueOf(params.get("id").toString()));
			List<InvoiceOrder> ls = invoiceOrderMapper.selectByExample(example);

			for (InvoiceOrder invoiceOrder : ls) {
				AccountingUnifiedCustomer dzMain = new AccountingUnifiedCustomer();

				Integer status = invoiceApplyMapperEx.findStatusBydzId(invoiceOrder.getDzId());

				dzMain.setId(invoiceOrder.getDzId());
				dzMain.setInvoiceStatus(status);

				accountingUnifiedCustomerMapper.updateByPrimaryKeySelective(dzMain);
			}
		}
	}

	@Override
	public List<InvoiceApplyExcel> getInvoiceApplyExcel(Map<String, Object> params) throws SuperdeskUniOrderException {
		return invoiceApplyMapperEx.getInvoiceApplyExcel(params);
	}

	/**
	 * 前端  客户结算 - 发票申请管理 - 详情
	 *
	 * @param params
	 * @return
	 * @throws SuperdeskUniOrderException
	 */
	@Override
	public InvoiceApplyVo getDetail(Map<String, Object> params) throws SuperdeskUniOrderException {

//		eg:
//		// 发票申请Id
//		params.put("id", getLong("id"));

		List<InvoiceApplyPage> invoiceApplyPageList = invoiceApplyMapperEx.selectByCondition(params);

		InvoiceApplyVo invoiceApplyVo = new InvoiceApplyVo();

		if (invoiceApplyPageList.size() > 0) {

			InvoiceApplyPage invoiceApplyPage = invoiceApplyPageList.get(0);

			BeanUtils.copyProperties(invoiceApplyPage, invoiceApplyVo);


			// TODO 坑位
			List<ViewDzOrder> dzOrders = invoiceApplyMapperEx.findDzOrderByGoodId(invoiceApplyVo.getId());

			// 先去查老的?如果没有再去查新的?
			if (dzOrders != null && dzOrders.size() > 0) {
				invoiceApplyVo.setDzOrders(dzOrders);
			} else {
				dzOrders = invoiceApplyMapperEx.findDzOrderByGoodIdNew(invoiceApplyVo.getId());
				invoiceApplyVo.setDzOrders(dzOrders);
			}

			return invoiceApplyVo;
		}

		return null;
	}

	@Override
	public void invoiceRegister(String token, Map<String, Object> params) throws SuperdeskUniOrderException {

		String userId = JwtUtil.checkToken(token);

		String invoiceNumber = params.get("invoiceNumber").toString();

		//dz add
		String           dateStr = params.get("datestr").toString();
		SimpleDateFormat sdf     = new SimpleDateFormat("yyyy-MM-dd");

		InvoiceApplyExample          example  = new InvoiceApplyExample();
		InvoiceApplyExample.Criteria criteria = example.createCriteria();
		criteria.andInvoiceNumberEqualTo(invoiceNumber);
		// TODO 写死
		criteria.andMakeInvoiceStatusEqualTo(1);
		List<InvoiceApply> invoiceApplyList = invoiceApplyMapper.selectByExample(example);
		if (invoiceApplyList != null && invoiceApplyList.size() > 0) {
			throw new SuperdeskUniOrderException(ExceptionMsg.INVOICE_EXIST);
		}

		InvoiceApply invoiceApply = new InvoiceApply();
		invoiceApply.setId(Long.valueOf(params.get("id").toString()));
		invoiceApply.setMakeUserId(Long.valueOf(userId));
		try {
			invoiceApply.setMakeInvoiceTime(sdf.parse(dateStr));
		} catch (ParseException e) {

			e.printStackTrace();
		}
		// TODO 写死
		invoiceApply.setMakeInvoiceStatus(1);
		invoiceApply.setInvoiceNumber(invoiceNumber);
		invoiceApplyMapper.updateByPrimaryKeySelective(invoiceApply);
	}

	@Override
	@Transactional
	public void sendInvoiceRegister(String token, List<Map> sendInvoiceRegisterList) throws SuperdeskUniOrderException {

		for (Map map : sendInvoiceRegisterList) {

			InvoiceApply invoiceApply = new InvoiceApply();
			// TODO 写死
			invoiceApply.setInvoiceStatus(1);
			invoiceApply.setMailTickTime(DateHelper.getNow());
			invoiceApply.setId(Long.valueOf(map.get("id").toString()));
			invoiceApply.setExpressCompanyId(Long.valueOf(map.get("expressCompanyId").toString()));

			if (map.get("expressNo") != null) {
				invoiceApply.setExpressNo(map.get("expressNo").toString());
			}

			invoiceApplyMapper.updateByPrimaryKeySelective(invoiceApply);
		}
	}

	/**
	 * 客户结算 - 发票管理 - opt 导入发票信息
	 *
	 * @param token
	 * @param list
	 * @throws SuperdeskUniOrderException
	 */
	@Override
	@Transactional
	public void importInvoiceExcel(String token, List<Map<String, Object>> list) throws SuperdeskUniOrderException {

		String userId = JwtUtil.checkToken(token);

		List<InvoiceApply> invoiceApplys = new ArrayList<>();

		boolean flag  = true;
		String  error = "";
		int     h     = 1;

		for (Map<String, Object> map : list) {

			InvoiceApplyExample          example  = new InvoiceApplyExample();
			InvoiceApplyExample.Criteria criteria = example.createCriteria();

			String invoiceNo     = map.get("invoiceNo").toString();
			String invoiceNumber = map.get("invoiceNumber").toString();

			criteria.andInvoiceNoEqualTo(invoiceNo);
			// TODO 写死
			criteria.andAuditStatusEqualTo(2);
			List<InvoiceApply> invoiceApplyList = invoiceApplyMapper.selectByExample(example);

			if (invoiceApplyList != null && invoiceApplyList.size() > 0) {
				InvoiceApply invoiceApply = invoiceApplyList.get(0);
				// TODO 写死
				invoiceApply.setMakeInvoiceStatus(1);
				invoiceApply.setMakeUserId(Long.valueOf(userId));
				invoiceApply.setMakeInvoiceTime(DateHelper.getNow());
				invoiceApply.setInvoiceNumber(invoiceNumber);
				invoiceApplys.add(invoiceApply);
			} else {
				flag = false;
				error += "第" + h + "行," + invoiceNo + ",该发票申请号错误或未审核通过.";
			}

			InvoiceApplyExample          example1  = new InvoiceApplyExample();
			InvoiceApplyExample.Criteria criteria1 = example1.createCriteria();
			criteria1.andInvoiceNumberEqualTo(invoiceNumber);
			// TODO 写死
			criteria1.andMakeInvoiceStatusEqualTo(1);

			List<InvoiceApply> invoiceApplyList1 = invoiceApplyMapper.selectByExample(example1);

			if (invoiceApplyList1 != null && invoiceApplyList1.size() > 0) {
				flag = false;
				error += "第" + h + "行," + invoiceNumber + ",该发票号已存在.";
			}

			h++;
		}

		if (flag) {
			for (InvoiceApply invoiceApply : invoiceApplys) {
				invoiceApplyMapper.updateByPrimaryKeySelective(invoiceApply);
			}
		} else {
			throw new SuperdeskUniOrderException(500, error);
		}
	}

	/**
	 * 客户结算 - 发票管理 - opt 导入寄票信息
	 *
	 * @param token
	 * @param list
	 * @throws SuperdeskUniOrderException
	 */
	@Override
	@Transactional
	public void importSendInvoiceExcel(String token, List<Map<String, Object>> list) throws SuperdeskUniOrderException {

		String             userId        = JwtUtil.checkToken(token);
		List<InvoiceApply> invoiceApplys = new ArrayList<>();
		boolean            flag          = true;
		String             error         = "";
		int                h             = 1;
		for (Map<String, Object> map : list) {
			InvoiceApplyExample          example       = new InvoiceApplyExample();
			InvoiceApplyExample.Criteria criteria      = example.createCriteria();
			String                       invoiceNumber = map.get("invoiceNumber").toString();
			criteria.andInvoiceNumberEqualTo(invoiceNumber);
			// TODO 写死
			criteria.andMakeInvoiceStatusEqualTo(1);
			List<InvoiceApply> invoiceApplyList = invoiceApplyMapper.selectByExample(example);

			if (invoiceApplyList != null && invoiceApplyList.size() > 0) {

				InvoiceApply invoiceApply = invoiceApplyList.get(0);
				// TODO 写死
				invoiceApply.setInvoiceStatus(1);
				invoiceApply.setMakeUserId(Long.valueOf(userId));
				invoiceApply.setMailTickTime(DateHelper.getNow());
				String               expressCompanyName = map.get("expressCompanyName").toString();
				List<ExpressCompany> expressCompanyList = expressCompanyMapper.selectByCompanyName(expressCompanyName);

				if (expressCompanyList != null && expressCompanyList.size() > 0) {
					ExpressCompany expressCompany = expressCompanyList.get(0);
					invoiceApply.setExpressCompanyId(expressCompany.getId());
				} else {
					flag = false;
					error += "第" + h + "行," + expressCompanyName + ",该快递公司名称不正确.";
				}

				if (map.get("expressNo") != null) {
					String expressNo = map.get("expressNo").toString();
					invoiceApply.setExpressNo(expressNo);
				}

				invoiceApplys.add(invoiceApply);
			} else {
				flag = false;
				error += "第" + h + "行," + invoiceNumber + ",该发票号未开票.";
			}
			h++;
		}

		if (flag) {
			for (InvoiceApply invoiceApply : invoiceApplys) {
				invoiceApplyMapper.updateByPrimaryKeySelective(invoiceApply);
			}
		} else {
			throw new SuperdeskUniOrderException(500, error);
		}
	}

	@Override
	@Transactional
	public void invoiceAgain(String token, Map<String, Object> params) throws SuperdeskUniOrderException {

		Long id = Long.valueOf(params.get("id").toString());

		InvoiceApply invoiceApply = invoiceApplyMapper.selectByPrimaryKey(id);

		// TODO 写死
		if (!invoiceApply.getBackAccountStatus().equals(0)) {
			throw new SuperdeskUniOrderException(ExceptionMsg.INVOICE_HAVE_BACK);
		}

		// TODO 写死
		invoiceApply.setAuditStatus(3);
		// TODO 写死
		invoiceApply.setMakeInvoiceStatus(2);
		// TODO 写死
		invoiceApply.setInvoiceStatus(2);
		invoiceApply.setExpressCompanyId(null);
		invoiceApply.setExpressNo(null);
		invoiceApply.setInvoiceNumber(null);

		invoiceApplyMapper.updateByPrimaryKey(invoiceApply);

		InvoiceOrderExample          example  = new InvoiceOrderExample();
		InvoiceOrderExample.Criteria criteria = example.createCriteria();
		criteria.andInvoiceApplyIdEqualTo(Long.valueOf(params.get("id").toString()));
		List<InvoiceOrder> ls = invoiceOrderMapper.selectByExample(example);
		for (InvoiceOrder invoiceOrder : ls) {

			AccountingUnifiedCustomer dzMain = new AccountingUnifiedCustomer();

			Integer status = invoiceApplyMapperEx.findStatusBydzId(invoiceOrder.getDzId());

			dzMain.setId(invoiceOrder.getDzId());
			dzMain.setInvoiceStatus(status);
			accountingUnifiedCustomerMapper.updateByPrimaryKeySelective(dzMain);
		}

	}

	@Override
	public List<ExpressCompany> findExpressCompany() throws SuperdeskUniOrderException {
		return expressCompanyMapper.findAll();
	}

	@Override
	public List<InvoiceApply> findAll(Map<String, Object> params) {
		return invoiceApplyMapperEx.findAll(params);
	}

	@Override
	public InvoiceApply findById(long id) {
		return invoiceApplyMapper.selectByPrimaryKey(id);
	}

	@Override
	public ResponseResult<List<InvoiceApply>> findInvoiceByPageNew(Map<String, Object> params, int pageNo, int pageSize) {
		PageHelper.startPage(pageNo, pageSize);

		List<InvoiceApply> ls = invoiceApplyMapperEx.findAll(params);

		PageInfo<InvoiceApply> page = new PageInfo<InvoiceApply>(ls);
		PageHelper.clearPage();
		return new ResponseResult<List<InvoiceApply>>(page.getPageNum(), page.getPageSize(), (int) page.getTotal(), ls);
	}

	@Override
//	@Cacheable(keyGenerator = "findByXXKeyGenerator")
	public List<InvoiceApply> findInvoiceBySn(Map<String, Object> invQuery) {
		return invoiceApplyMapperEx.findInvoiceBySn(invQuery);
	}

	private Map<String, Object> GetConfigByINVA() {

		Map<String, Object> map    = new HashMap<>();
		SysConfig           config = sysConfigMapper.selectByPrimaryKey("INVA");
		SimpleDateFormat    sdf    = new SimpleDateFormat("yyyyMMdd");
		Date                dtnow  = new Date();

		if (sdf.format(dtnow).equals(sdf.format(config.getValueDate()))) {
			map.put("valueDate", config.getValueDate().getTime());
			map.put("key", "INVA");
			map.put("valueInt", config.getValueInt() + 1);
			String intStr    = String.valueOf(config.getValueInt() + 1);
			String resintStr = intStr;
			for (int i = intStr.length(); i <= 4; i++) {
				resintStr = "0" + resintStr;
			}
			map.put("sn", config.getValueStr1() + sdf.format(config.getValueDate()) + resintStr);
		} else {
			map.put("valueDate", dtnow.getTime());
			map.put("key", "INVA");
			map.put("valueInt", "1");
			map.put("sn", config.getValueStr1() + sdf.format(dtnow) + "00001");
		}
		return map;
	}

	public static List<Long> arrToListRemoval(String[] arrStr) {
		List<Long> list = new ArrayList<>();
		for (int i = 0; i < arrStr.length; i++) {
			if (!list.contains(arrStr[i])) {
				list.add(Long.valueOf(arrStr[i]));
			}
		}
		return list;
	}
}
