package io.renren.modules.business.controller;

import io.renren.common.utils.*;
import io.renren.modules.business.entity.*;
import io.renren.modules.business.service.*;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;


/**
 * 支出明细表
 *
 * @author jiaqiao
 * @email jiaqiao@163.com
 * @date 2022-10-13 10:00:10
 */
@RestController
@RequestMapping("business/businessoutlay")
public class BusinessOutlayController {
    @Autowired
    private BusinessOutlayService businessOutlayService;
    @Autowired
    private BusinessDictService businessDictService;
    @Autowired
    private BusinessProjectService businessProjectService;
    @Autowired
    private BusinessWorkerService businessWorkerService;
    @Autowired
    private BusinessAnnualService businessAnnualService;
    @Autowired
    private BusinessOutlayIncomeService businessOutlayIncomeService;

    /**
     * 列表
     */
    @RequestMapping("/list")
    @RequiresPermissions("business:businessoutlay:list")
    public R list(@RequestParam Map<String, Object> params){
        PageUtils page = businessOutlayService.queryPage(params);

        return R.ok().put("page", page);
    }

    /**
     * 列表 状态为 0 并且不含有翻页
     * @param params
     * @return
     */
    @RequestMapping("/listNoPage")
    @RequiresPermissions("business:businessoutlay:list")
    public R listNoPage(@RequestParam Map<String, Object> params){
        List<BusinessOutlayEntity> page = businessOutlayService.listNoPage(params);
        return R.ok().put("page", page);
    }

    /**
     * 列表 PC端含翻页
     * @param params
     * @return
     */
    @RequestMapping("/pcListNoPage")
    @RequiresPermissions("business:businessoutlay:list")
    public R pcListNoPage(@RequestParam Map<String, Object> params){
        PageUtils page = businessOutlayService.pcListPage(params);
        return R.ok().put("page", page);
    }

    /**
     * 列表 状态为 0 并且不含有翻页  获取当前年度数据
     * @param params
     * @return
     */
    @RequestMapping("/listNowTime")
    @RequiresPermissions("business:businessoutlay:list")
    public R listNowTime(@RequestParam Map<String, Object> params){
        List<BusinessOutlayEntity> page = businessOutlayService.listNowTime(params);

        return R.ok().put("page", page);
    }

    /**
     * 获取所有的立项列表未删除的
     */
    @RequestMapping("/allList")
    @RequiresPermissions("business:businessoutlay:list")
    public R allList(){
        //System.out.println(params);
        List<BusinessProjectEntity> page = businessProjectService.allList();
        return R.ok().put("page", page);
    }

    /**
     * 获取字典信息
     */
    @RequestMapping("/dictList")
    @RequiresPermissions("business:businessoutlay:list")
    public R dictList(@RequestParam Map<String, Object> params){
        // PageUtils page = businessDictService.queryPage(params);
        List<BusinessDictEntity> businessDictEntitys = businessDictService.listWithTree();
        return R.ok().put("data", businessDictEntitys);
    }

    /**
     * 包含离职列表
     */
    @RequestMapping("/selectAllContainsDeparturePage")
    @RequiresPermissions("business:businessoutlay:list")
    public R selectAllContainsDeparturePage(@RequestParam Map<String, Object> params) {
        List<BusinessWorkerEntity> page = businessWorkerService.selectAllContainsDeparture(params);
        return R.ok().put("page", page);
    }

    /**
     * 信息
     */
    @RequestMapping("/info/{id}")
    @RequiresPermissions("business:businessoutlay:info")
    public R info(@PathVariable("id") Integer id){
		BusinessOutlayEntity businessOutlay = businessOutlayService.getById(id);

        return R.ok().put("businessOutlay", businessOutlay);
    }

    /**
     * 保存
     */
    @RequestMapping("/save")
    @RequiresPermissions("business:businessoutlay:save")
    public R save(@RequestBody BusinessOutlayEntity businessOutlay) throws ParseException {
        // 查询今天是否已经提交总结
        Map<String, Object> param = new HashMap<>();
        param.put("start", DateUtils.format(businessOutlay.getOutTime()));
        param.put("writeUserId", businessOutlay.getWriteUserId());
        if(businessOutlayIncomeService.getLockedCnt(param) > 0) {
            return R.error("所选日期已经阶段提交，无法添加明细！");
        }
        BusinessOutlayEntity businessOutlayOld = null;
        if(businessOutlay.getId() == null || businessOutlay.getId() == 0) {
            businessOutlay.setCreateTime(new Date());
            businessOutlay.setUpdateTime(new Date());
            businessOutlayService.save(businessOutlay);
//            businessOutlayService.ifSave(businessOutlay.getOutTime(),businessOutlay.getWriteUserId().toString(),0);
        } else {
            businessOutlayOld = businessOutlayService.getById(businessOutlay.getId());//通过ID取原数据的日期，用来比较日期重新计算收支
            businessOutlay.setUpdateTime(new Date());
            businessOutlayService.updateById(businessOutlay);
        }
        if(businessOutlay.getWriteUserId()!=null && businessOutlay.getWriteUserId()!= 10 && businessOutlay.getWriteUserId()!= 1){
            afresh(businessOutlay,businessOutlayOld);
        }
        return R.ok();
    }

    /***
     * 重新计算
     * 支出修改或新增时：
     * 1、判断收支是否存在，不存在则创建
     * 2、判断是否是修改了时间（原支出数据获取时间，通过原时间和新时间进行比较），取最小时间为其实开始重新计算
     * 3、判断最小时间的收支是否存在，不存在则创建，存在则修改此日支出金额、今日余额
     * 4、循环修改最小时间之后的收支数据，直到没有下一日数据为止
     */
    private void afresh(BusinessOutlayEntity businessOutlay,BusinessOutlayEntity businessOutlayOld){
        Map<String, Object> param = new HashMap<>();
        Date outTime = businessOutlay.getOutTime();
        param.put("outinDate", outTime);
        param.put("writeUserId", businessOutlay.getWriteUserId());
        param.put("userId", businessOutlay.getWriteUserId());
        param.put("startTime", DateUtils.format(outTime));
        param.put("endTime", DateUtils.format(outTime));
        //判断新日期是否有收支数据，没有则创建
        BusinessOutlayIncomeEntity incomeEntity = businessOutlayIncomeService.getOutInByDate(param);
        if(incomeEntity!=null){

        }else{
            //新增，1、取昨天数据（今日之前的最大日期的数据中）的今日余额；2、今日收入暂置成0；3、取当前的支出汇总；4、计算今日余额；5、增加收支数据
            incomeEntity = new BusinessOutlayIncomeEntity();
            incomeEntity.setOutinDate(outTime);//日期
            // 查询昨日余额，就是总结里除去今天最大一天的今日余额
            BigDecimal zrye = businessOutlayIncomeService.getZrye(param);
            Double zryeb = 0d;
            if(zrye != null){
                zryeb = zrye.doubleValue();
            }
            incomeEntity.setOutinYdayBalance(zryeb);//昨日余额
            incomeEntity.setOutinTdayIncome(0);//今日收入
            Double jrzc = businessOutlayService.getTotalByHJGId(param);
            if(jrzc == null) {
                jrzc = 0d;
            }
            incomeEntity.setOutinTdayOut(jrzc);//今日支出
            Double jrye = zryeb - jrzc;
            incomeEntity.setOutinTdayBalance(jrye);//今日余额
            incomeEntity.setStatus(0);
            incomeEntity.setApproval(0);
            incomeEntity.setWriteUserId(businessOutlay.getWriteUserId());
            incomeEntity.setCreateTime(new Date());
            incomeEntity.setUpdateTime(new Date());
            businessOutlayIncomeService.save(incomeEntity);
        }

        //判断原日期与新日期，原日期如比新日期小，则从原日期时间开始重新计算
        if(businessOutlayOld!=null){
            Date outTimeOld = businessOutlayOld.getOutTime();
            if (outTimeOld.compareTo(outTime) < 0) {
                outTime = outTimeOld;
            }
        }

        param.put("outinDate", outTime);
        param.put("writeUserId", businessOutlay.getWriteUserId());
        param.put("userId", businessOutlay.getWriteUserId());
        param.put("startTime", DateUtils.format(outTime));
        param.put("endTime", DateUtils.format(outTime));

        incomeEntity = businessOutlayIncomeService.getOutInByDate(param);
        if(incomeEntity!=null){
            //修改，1、获取当前的支出汇总；2、计算今日余额；3、修改
            Double zrye = incomeEntity.getOutinYdayBalance();//昨日余额
            if(zrye == null) {
                zrye = 0d;
            }
            Double jrsr = incomeEntity.getOutinTdayIncome();//今日收入
            if(jrsr == null) {
                jrsr = 0d;
            }
            Double jrzc = businessOutlayService.getTotalByHJGId(param);
            if(jrzc == null) {
                jrzc = 0d;
            }
            incomeEntity.setOutinTdayOut(jrzc);//今日支出
            Double jrye = zrye + jrsr - jrzc;
            incomeEntity.setOutinTdayBalance(jrye);//今日余额
            incomeEntity.setUpdateTime(new Date());
            businessOutlayIncomeService.updateById(incomeEntity);
        }else{
            //新增，1、取昨天数据（今日之前的最大日期的数据中）的今日余额；2、今日收入暂置成0；3、取当前的支出汇总；4、计算今日余额；5、增加收支数据
            incomeEntity = new BusinessOutlayIncomeEntity();
            incomeEntity.setOutinDate(outTime);//日期
            // 查询昨日余额，就是总结里除去今天最大一天的今日余额
            BigDecimal zrye = businessOutlayIncomeService.getZrye(param);
            Double zryeb = 0d;
            if(zrye != null){
                zryeb = zrye.doubleValue();
            }
            incomeEntity.setOutinYdayBalance(zryeb);//昨日余额
            incomeEntity.setOutinTdayIncome(0);//今日收入

            Double jrzc = businessOutlayService.getTotalByHJGId(param);
            if(jrzc == null) {
                jrzc = 0d;
            }
            incomeEntity.setOutinTdayOut(jrzc);//今日支出
            Double jrye = zryeb - jrzc;
            incomeEntity.setOutinTdayBalance(jrye);//今日余额
            incomeEntity.setStatus(0);
            incomeEntity.setApproval(0);
            incomeEntity.setWriteUserId(businessOutlay.getWriteUserId());
            incomeEntity.setCreateTime(new Date());
            incomeEntity.setUpdateTime(new Date());
            businessOutlayIncomeService.save(incomeEntity);
        }
        //获取要修改的下一日收支数据，并修改
        afreshNext(incomeEntity);
    }

    /**
     * 获取要修改的下一日收支数据，并修改
     * 判断是否有下一日期收支数据，有则进行获取重新计算；无则跳出计算
     */
    private void afreshNext(BusinessOutlayIncomeEntity businessOutlayIncomeEntity){
        Map<String, Object> param = new HashMap<>();
        param.put("outinDate", businessOutlayIncomeEntity.getOutinDate());
        param.put("writeUserId", businessOutlayIncomeEntity.getWriteUserId());
        //获取下一日期收支数据
        BusinessOutlayIncomeEntity incomeEntity = businessOutlayIncomeService.getNextOutInByDate(param);
        if(incomeEntity!=null){
            Double zrye = businessOutlayIncomeEntity.getOutinTdayBalance(); //今日余额是下一日期的昨日余额
            incomeEntity.setOutinYdayBalance(zrye);
            Double jrsr = incomeEntity.getOutinTdayIncome();//今日收入
            if(jrsr == null) {
                jrsr = 0d;
            }
            param.put("userId", businessOutlayIncomeEntity.getWriteUserId());
            param.put("startTime", DateUtils.format(incomeEntity.getOutinDate()));
            param.put("endTime", DateUtils.format(incomeEntity.getOutinDate()));
            Double jrzc = businessOutlayService.getTotalByHJGId(param);
            if(jrzc == null) {
                jrzc = 0d;
            }
            incomeEntity.setOutinTdayOut(jrzc);//今日支出
            Double jrye = zrye + jrsr - jrzc;
            incomeEntity.setOutinTdayBalance(jrye);//今日余额
            incomeEntity.setUpdateTime(new Date());
            businessOutlayIncomeService.updateById(incomeEntity);
            afreshNext(incomeEntity);//递归
        }
    }

    /**
     * 修改
     */
    @RequestMapping("/update")
    @RequiresPermissions("business:businessoutlay:update")
    public R update(@RequestBody BusinessOutlayEntity businessOutlay){
		businessOutlayService.updateById(businessOutlay);
		// 根据填入的时间和填写人去是否向年度总结表添加数据
        return R.ok();
    }

    /**
     * 删除
     */
    @RequestMapping("/delete")
    @RequiresPermissions("business:businessoutlay:delete")
    public R delete(@RequestBody Integer[] ids){
		businessOutlayService.removeByIds(Arrays.asList(ids));

        return R.ok();
    }

    /**
     * 锁住
     */
    @RequestMapping("/updateLocked")
    @RequiresPermissions("business:businessoutlay:update")
    public R updateLocked(String userId){
        businessOutlayService.updateLocked(userId);
        businessOutlayIncomeService.updateLocked(userId);
        return R.ok();
    }

    /**
     * 导出
     */
    @RequestMapping("/export")
    public void export(HttpServletResponse response, HttpServletRequest request){
        String start = request.getParameter("start");
        String end = request.getParameter("end");
        Map<String, Object> params = new HashMap<>();
        params.put("start",start);
        params.put("end",end);
        List<BusinessOutlayEntity> list = businessOutlayService.pcListNoPage(params);
        ExcelUtil<BusinessOutlayEntity> util = new ExcelUtil<BusinessOutlayEntity>(BusinessOutlayEntity.class);
        R r = util.exportExcel(list, "支出明细");
        try {
            String filename = r.get("msg") + "";
            String filepath = FileUtils.getTempDirectoryPath() + File.separator + filename;
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, filename);
            FileUtils.writeBytes(filepath, response.getOutputStream());
            FileUtils.deleteFile(filepath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
