package com.tax.file.service.impl;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tax.file.constants.CommonConstants;
import com.tax.file.model.*;
import com.tax.file.service.api.FileServerService;
import com.tax.file.service.api.TkTaxUserService;
import com.tax.file.utils.InvoiceUtil;
import com.tax.file.utils.NationDic;
import com.tax.file.utils.NationUtil;
import com.tax.file.utils.token.TokenFactory;
import com.yxcheng.token.common.enumutil.ResultEnum;
import com.yxcheng.token.common.model.JsonResult;
import com.yxcheng.token.common.service.AbstractService;
import com.tax.file.mapper.FIncomeInvoiceMapper;
import com.tax.file.service.api.FIncomeInvoiceService;
import com.yxcheng.token.utils.DateUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

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


@Transactional
@Component
@ComponentScan(basePackages = {"com.tax.file.dao", "com.tax.file.integration"})
public class FIncomeInvoiceServiceImpl extends AbstractService<FIncomeInvoiceMapper,FIncomeInvoiceExample,FIncomeInvoice> implements FIncomeInvoiceService {

    private static final Logger logger = LoggerFactory.getLogger(FIncomeInvoiceServiceImpl.class);
    @Autowired
    protected TkTaxUserService tkTaxUserService;
    @Autowired
    protected FileServerService fileServerService;

    @Override
    public JsonResult<List<InvoiceApplyRes>> apply(IncomeApplyReq incomeApplyReq){
        JsonResult<List<InvoiceApplyRes>> result = new JsonResult<>();
        try {
            List<InvoiceApplyReq> dataList = incomeApplyReq.getInvoiceList();
            if (dataList != null && dataList.size() > 0) {
                List<InvoiceApplyRes> list = new ArrayList<>();
                boolean flag = true;

                List<InvoiceApplyReq> insertList = new ArrayList<>();
                List<FIncomeInvoice> updateList = new ArrayList<>();
                Map<String, String> duplicateMap = new HashMap<>();
                for (InvoiceApplyReq entity : dataList) {
                    InvoiceApplyRes res = checkInvoiceApply(entity, duplicateMap);
                    list.add(res);
                    if (!"0".equals(res.getErrorCode())) {
                        flag = false;
                    }
                    FIncomeInvoice fincomeInvoice = this.getFincomeInvoice(entity.getInvKind(), entity.getInvNum(), incomeApplyReq.getAccessKeyID());
                    if (fincomeInvoice == null) {
                        entity.setCreateDate(new Date());
                        entity.setTaxno(incomeApplyReq.getTaxno());
                        entity.setUserName(incomeApplyReq.getAccessKeyID());
                        insertList.add(entity);
                    } else {
                        Date invDate = DateUtils.parseDate(entity.getInvDate(), "yyyy-MM-dd");
                        if (!fincomeInvoice.getIsIncome().equals(entity.getIsIncome())) {
                            fincomeInvoice.setIsIncome(entity.getIsIncome());
                            initFIncomeInvoice(fincomeInvoice);
                            updateList.add(fincomeInvoice);
                        } else if (!fincomeInvoice.getIncomeMonth().equals(entity.getIncomeMonth())) {
                            fincomeInvoice.setIncomeMonth(entity.getIncomeMonth());
                            initFIncomeInvoice(fincomeInvoice);
                            updateList.add(fincomeInvoice);
                        } else if (fincomeInvoice.getInvDate().compareTo(invDate) != 0) {
                            fincomeInvoice.setInvDate(invDate);
                            initFIncomeInvoice(fincomeInvoice);
                            updateList.add(fincomeInvoice);
                        } else {
                            res.setErrorMsg("已申请");
                            res.setErrorCode("31");
                        }


                    }
                }

                if (flag) {
                    if (insertList.size() > 0) {
                        insertAppyList(insertList);
                    }
                    if (updateList.size() > 0) {
                        updateApplyList(updateList);
                    }
                } else {
                    result.setSuccess(false);
                    result.setErrorCode("-1");
                }

                result.setData(list);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return result;
    }


    private void initFIncomeInvoice(FIncomeInvoice fincomeInvoice){
        fincomeInvoice.setApplyStatus("0");
        fincomeInvoice.setDownStatus("0");
        fincomeInvoice.setResStatus("0");
        fincomeInvoice.setDownStatus("0");
    }

    private void updateApplyList(List<FIncomeInvoice> updateList) {
        for(FIncomeInvoice entity:updateList){
            this.baseMapper.updateByPrimaryKeySelective(entity);
        }
    }

    @Override
    public JsonResult<IncomeResultRes> result(IncomeResultReq incomeResultReq) {
        JsonResult<IncomeResultRes>result = new JsonResult<>();
        IncomeResultRes res = new IncomeResultRes();

        Map param = new HashMap();
        param.put("userName",incomeResultReq.getAccessKeyID());
        param.put("pageSize",CommonConstants.PAGE_SIZE);
        List<FIncomeInvoice>list = this.baseMapper.getIncomeInvoicePage(param);
        if(list==null || list.size()==0){
            res.setTaskno("");
            res.setFollowTask(false);
            res.setQuantity(0);
            res.setInvoiceList(null);
            result.setData(res);
            return result;
        }

        String taskno = UUID.randomUUID().toString();
        String tasknoOut = null;
        boolean flag = true;

        for(FIncomeInvoice entity : list){
            if(StringUtils.isNotBlank(entity.getTaskno())){
                tasknoOut = entity.getTaskno();
            }
            int reqCount = entity.getReqCount();
            if(reqCount<5){
                flag = false;
            }
            entity.setReqCount(reqCount+1);
            entity.setTaskno(taskno);
        }

        if(flag){
            result.errorResponse(ResultEnum.file_down_repeat_error);
            res.setTaskno(tasknoOut);
            result.setData(res);
            return result;
        }


        int len = this.baseMapper.updateTasknoBatch(list);
        logger.info("普票入账，更新任务编号："+len+",用户名:"+incomeResultReq.getAccessKeyID());

        List<InvoiceResultRes> invoiceList = getInvoice(list);
        res.setInvoiceList(invoiceList);
        res.setQuantity(invoiceList.size());
        res.setTaskno(taskno);
        res.setFollowTask(invoiceList.size()==CommonConstants.PAGE_SIZE);
        result.setData(res);
        return result;
    }

    @Override
    public JsonResult<String> feedback(IncomeResultReq incomeResultReq) {
        int count = this.baseMapper.getIncomeByTaskNo(incomeResultReq.getTaskno());
        if(count == 0){
            return new JsonResult().errorResponse(ResultEnum.file_taskno_error);
        }

        FIncomeInvoice incomeInvoice = new FIncomeInvoice();
        incomeInvoice.setResStatus("1");
        incomeInvoice.setResTime(new Date());

        FIncomeInvoiceExample example = new FIncomeInvoiceExample();
        example.createCriteria().andTasknoEqualTo(incomeResultReq.getTaskno());

        this.baseMapper.updateByExampleSelective(incomeInvoice,example);
        logger.info("普票入账反馈，任务编号："+incomeResultReq.getTaskno()+",更新记录数量："+count);
        return new JsonResult<>();
    }

    @Override
    public JsonResult<IncomeQueryRes> query(IncomeQueryReq incomeQueryReq) {
        JsonResult<IncomeQueryRes>result = new JsonResult<>();
        IncomeQueryRes res = new IncomeQueryRes();

        TkTaxUserExample taxUserExample = new TkTaxUserExample();
        taxUserExample.createCriteria().andTaxnoEqualTo(incomeQueryReq.getTaxno());

        TkTaxUser taxUser = tkTaxUserService.getOne(taxUserExample);


        FileServerExample fileServerExample = new FileServerExample();
        fileServerExample.createCriteria().andServerNoEqualTo(taxUser.getServerNo());

        FileServer fileServer = fileServerService.getOne(fileServerExample);

        try {
            String tokenCode = TokenFactory.getTokenCode(taxUser, fileServer);

            FIncomeInvoice entity = new FIncomeInvoice();
            entity.setTaxno(incomeQueryReq.getTaxno());
            entity.setToken(tokenCode);
            entity.setZoneCode(incomeQueryReq.getZoneCode());
            entity.setInvKind(incomeQueryReq.getInvKind());
            entity.setInvNum(incomeQueryReq.getInvNum());

            JSONObject jsonObject = NationUtil.incomeSingleQuery(entity);

            if("01".equals(jsonObject.getString("key1"))){
                JSONObject key3 = jsonObject.getJSONObject("key3");
                List<InvoiceQueryRes> invoiceList = getSingInvoice(key3.getJSONArray("aaData"));
                res.setQuantity(key3.getInteger("iTotalRecords"));
                res.setInvoiceList(invoiceList);
                result.setData(res);
            }else{
                result.setErrorCode(jsonObject.getString("key1"));
               // result.setMessage(jsonObject.getString("key1"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    private List<InvoiceQueryRes> getSingInvoice(JSONArray data) {
        List<InvoiceQueryRes> list = new ArrayList<>();
        if(data!=null && data.size()>0){
            for(int i=0;i<data.size();i++){
                JSONArray jsonArray = data.getJSONArray(i);
                InvoiceQueryRes res = new InvoiceQueryRes();
                res.setInvKind(jsonArray.getString(1));
                res.setInvNum(jsonArray.getString(2));
                res.setIncomeFlag(NationDic.incomeDic.get(jsonArray.getString(3)));
                res.setIncomeMonth(jsonArray.getString(4));
                res.setResult(jsonArray.getString(5));
                list.add(res);
            }
        }
        return list;
    }

    private List<InvoiceResultRes> getInvoice(List<FIncomeInvoice> list) {
        List<InvoiceResultRes> dataList = new ArrayList<>();
        if(list!=null && list.size()>0){
            for(FIncomeInvoice entity : list){
                InvoiceResultRes res = new InvoiceResultRes();
                res.setInvKind(entity.getInvKind());
                res.setInvNum(entity.getInvNum());
                res.setIncomeMonth(entity.getIncomeMonth());
                res.setInvDate(entity.getInvDate()!= null?new SimpleDateFormat("yyyy-MM-dd").format(entity.getInvDate()):"");
                res.setResult(entity.getResult());
                dataList.add(res);
            }
        }
        return dataList;
    }

    private FIncomeInvoice getFincomeInvoice(String invKind, String invNum,String userName) {
        FIncomeInvoiceExample example = new FIncomeInvoiceExample();
        example.createCriteria().andInvKindEqualTo(invKind).andInvNumEqualTo(invNum).andUserNameEqualTo(userName);
        return this.getOne(example);
    }

    private void insertAppyList(List<InvoiceApplyReq> dataList) {
        this.baseMapper.insertAppyList(dataList);
    }

    private InvoiceApplyRes checkInvoiceApply(InvoiceApplyReq invoiceApplyReq, Map<String, String> duplicateMap) {
        InvoiceApplyRes res = new InvoiceApplyRes();

        String invKind = invoiceApplyReq.getInvKind();
        String invNum = invoiceApplyReq.getInvNum();
        String invDate = invoiceApplyReq.getInvDate();
        String isInCome = invoiceApplyReq.getIsIncome();
        String incomeMonth = invoiceApplyReq.getIncomeMonth();
        res.setInvKind(invKind);
        res.setInvNum(invNum);
        if(duplicateMap.containsKey(invKind+invNum)){
            res.setErrorCode("30");
            res.setErrorMsg("发票代码、发票号码重复");
            return res;
        }else{
            duplicateMap.put(invKind+invNum,"1");
        }

        if(!InvoiceUtil.isLengthCorrectForInvKind(invKind)){
            res.setErrorCode("24");
            res.setErrorMsg("发票代码应为10位或12位数字");
            return res;
        }

        if(!InvoiceUtil.isIncomeInvoiceForInvKind(invKind)){
            res.setErrorCode("23");
            res.setErrorMsg("发票代码不合法，增值税专用发票、机动车销售统一发票不能入账");
            return res;
        }


        if(!InvoiceUtil.isLengthCorrectForInvNum(invNum)){
            res.setErrorCode("25");
            res.setErrorMsg("发票号码应为8位数字");
            return res;
        }

        if(!InvoiceUtil.isIncomeCorrect(isInCome)){
            res.setErrorCode("27");
            res.setErrorMsg("是否入账不应为“0”或“1”以外的值");
            return res;
        }

        if(!InvoiceUtil.isInvDateFormatCorrect(invDate)){
            res.setErrorCode("26");
            res.setErrorMsg("开票日期格式错误，请修改为yyyy-mm-dd格式");
            return res;
        }

        if(!InvoiceUtil.isIncomeMonthFormatCorrect(incomeMonth)){
            res.setErrorCode("28");
            res.setErrorMsg("入账所属期格式错误，请修改为yyyyMM格式");
            return res;
        }

        if(!InvoiceUtil.isIncomeMonthCorrect(incomeMonth,invDate)){
            res.setErrorCode("13");
            res.setErrorMsg("入账月份大于当前自然月或开票月份大于入账月份");
            return res;
        }

        res.setErrorCode("0");
        res.setErrorMsg("正常");
        return res;
    }


    public static void main(String[] args) throws ParseException {

        Date date = DateUtils.parseDate("2019-02-02", "yyyy-MM-dd");
        Date date1 = DateUtils.parseDate("2019-03-02", "yyyy-MM-dd");
        System.out.println(date.compareTo(date1));
    }
}
