package cn.ezhizao.project.business.receiveTicket.controller;

import java.sql.Timestamp;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import cn.ezhizao.common.utils.SecurityUtils;
import cn.ezhizao.common.utils.StringUtils;
import cn.ezhizao.project.business.company.domain.BizCompany;
import cn.ezhizao.project.business.company.service.IBizCompanyService;
import cn.ezhizao.project.business.keepAccounts.domain.BizFinancialKeepAccount;
import cn.ezhizao.project.business.keepAccounts.domain.BizFinancialKeepAccountDetail;
import cn.ezhizao.project.business.keepAccounts.service.IBizFinancialKeepAccountDetailService;
import cn.ezhizao.project.business.keepAccounts.service.IBizFinancialKeepAccountService;
import cn.ezhizao.project.business.receiveTicket.domain.BizFinancialReceiveTicketDetail;
import cn.ezhizao.project.business.receiveTicket.domain.BizFinancialReceiveTicketFeedback;
import cn.ezhizao.project.business.receiveTicket.service.IBizFinancialReceiveTicketDetailService;
import cn.ezhizao.project.business.receiveTicket.service.IBizFinancialReceiveTicketFeedbackService;
import cn.ezhizao.project.business.salary.domain.BizFinancialSalary;
import cn.ezhizao.project.business.salary.domain.BizFinancialSalaryDetail;
import cn.ezhizao.project.business.salary.domain.BizFinancialSalaryDetailEmployee;
import cn.ezhizao.project.business.salary.service.IBizFinancialSalaryDetailEmployeeService;
import cn.ezhizao.project.business.salary.service.IBizFinancialSalaryDetailService;
import cn.ezhizao.project.business.workOrder.domain.BizWorkOrderRecord;
import cn.ezhizao.project.business.workOrder.service.IBizWorkOrderRecordService;
import cn.ezhizao.project.system.domain.SysUser;
import cn.ezhizao.project.system.mapper.SysUserMapper;
import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import cn.ezhizao.framework.aspectj.lang.annotation.Log;
import cn.ezhizao.framework.aspectj.lang.enums.BusinessType;
import cn.ezhizao.project.business.receiveTicket.domain.BizFinancialReceiveTicket;
import cn.ezhizao.project.business.receiveTicket.service.IBizFinancialReceiveTicketService;
import cn.ezhizao.framework.web.controller.BaseController;
import cn.ezhizao.framework.web.domain.AjaxResult;
import cn.ezhizao.common.utils.poi.ExcelUtil;
import cn.ezhizao.framework.web.page.TableDataInfo;

/**
 * 收票任务Controller
 *
 * @author ruoyi
 * @date 2023-11-17
 */
@RestController
@RequestMapping("/business/receiveTicket")
public class BizFinancialReceiveTicketController extends BaseController {
    @Resource
    private IBizFinancialReceiveTicketService bizFinancialReceiveTicketService;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private IBizFinancialReceiveTicketDetailService financialReceiveTicketDetailService;
    @Resource
    private IBizFinancialReceiveTicketFeedbackService financialReceiveTicketFeedbackService;
    @Resource
    private IBizFinancialKeepAccountService financialKeepAccountService;
    @Resource
    private IBizFinancialKeepAccountDetailService financialKeepAccountDetailService;
    @Resource
    private IBizFinancialSalaryDetailService financialSalaryDetailService;
    @Resource
    private IBizFinancialSalaryDetailEmployeeService financialSalaryDetailEmployeeService;
    @Resource
    private IBizCompanyService companyService;
    @Resource
    private IBizWorkOrderRecordService bizWorkOrderRecordService;


    /**
     * 查询收票任务列表
     */
    @PreAuthorize("@ss.hasPermi('business:receiveTicket:list')")
    @GetMapping("/list")
    public TableDataInfo list(BizFinancialReceiveTicket bizFinancialReceiveTicket) throws NoSuchFieldException, IllegalAccessException {
        String chooseYear = bizFinancialReceiveTicket.getYear();
        int nwoYear = LocalDate.now().getYear();
        setTenantId(bizFinancialReceiveTicket);
        startPage();
        startOrderBy();
        bizFinancialReceiveTicket.setIsZero(0);
        bizFinancialReceiveTicket.setYear(String.valueOf(nwoYear));
        List<BizFinancialReceiveTicket> list = bizFinancialReceiveTicketService.getList(bizFinancialReceiveTicket);
        if (!list.isEmpty()) {
            if (!chooseYear.equals(nwoYear)){
                List<BizFinancialReceiveTicketDetail> details = financialReceiveTicketDetailService.query().in("financial_receive_ticket_id", list.stream().map(BizFinancialReceiveTicket::getId).collect(Collectors.toList())).eq("year",chooseYear).list();
                list.forEach(l -> {
                    l.setDetails(details.stream().filter(v -> v.getFinancialReceiveTicketId().equals(l.getId())).collect(Collectors.toList()));
                });
            }else{
                List<BizFinancialReceiveTicketDetail> details = financialReceiveTicketDetailService.query().in("financial_receive_ticket_id", list.stream().map(BizFinancialReceiveTicket::getId).collect(Collectors.toList())).eq("year",bizFinancialReceiveTicket.getYear()).list();
                list.forEach(l -> {
                    l.setDetails(details.stream().filter(v -> v.getFinancialReceiveTicketId().equals(l.getId())).collect(Collectors.toList()));
                });
            }

        }
        return getDataTable(list);
    }

    @PreAuthorize("@ss.hasAnyPermi('business:receiveTicket:query,business:receiveTicket:view')")
    @PostMapping("/getDetail")
    public AjaxResult getDetail(@RequestBody BizFinancialReceiveTicketDetail details) {
        List<BizFinancialReceiveTicketDetail> bizFinancialSalaryDetails = financialReceiveTicketDetailService.getList(details);
        if (bizFinancialSalaryDetails.isEmpty()) {
            if (StringUtils.isEmpty(details.getCompanyName())) {
                BizCompany company = companyService.getById(details.getCompanyId());
                details.setCompanyName(company == null ? "" : company.getName());
            }
            return success(details);
        }
        return success(bizFinancialSalaryDetails.get(0));
    }

    @ApiOperation("根据客户id和当前年月获取当前工资信息")
    @PostMapping("/getSalaryDetail")
    @PreAuthorize("@ss.hasAnyPermi('business:receiveTicket:query,business:receiveTicket:view')")
    @ResponseBody
    public AjaxResult getSalaryDetailByCondition(@RequestBody BizFinancialSalaryDetail conditions) {
        BizFinancialSalaryDetail detail = financialSalaryDetailService.getList(conditions).stream().findFirst().orElse(null);
        return success(detail);
    }

    /**
     * 导出收票任务列表
     */
    @PreAuthorize("@ss.hasPermi('business:receiveTicket:export')")
    @Log(title = "收票任务", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, BizFinancialReceiveTicket bizFinancialReceiveTicket) throws NoSuchFieldException, IllegalAccessException {
        setTenantId(bizFinancialReceiveTicket);
        startOrderBy();
        bizFinancialReceiveTicket.setIsZero(0);
//        List<BizFinancialReceiveTicket> list = bizFinancialReceiveTicketService.getList(bizFinancialReceiveTicket);
        List<BizFinancialReceiveTicket> list = bizFinancialReceiveTicketService.getList2(bizFinancialReceiveTicket);
        for (BizFinancialReceiveTicket l : list) {
            l.setCurrentPeriod(bizFinancialReceiveTicket.getYear() + "-" + bizFinancialReceiveTicket.getMonth());
            BizFinancialReceiveTicketDetail detail = new BizFinancialReceiveTicketDetail();
            detail.setFinancialReceiveTicketId(l.getId());
            detail.setYear(bizFinancialReceiveTicket.getYear());
            detail.setMonth(bizFinancialReceiveTicket.getMonth());
            List<BizFinancialReceiveTicketDetail> ticketDetail = financialReceiveTicketDetailService.getList(detail);
            if (ticketDetail.size() == 0) {
                detail.setStatus(0);
                l.setServiceName("");
            } else {
                detail = ticketDetail.get(0);
                SysUser sysUser = sysUserMapper.selectUserById(detail.getVerifierId());
                l.setServiceName(sysUser == null ? "" : sysUser.getNickName());
            }
            //设置状态
            switch (detail.getStatus()) {
                case 0:
                    l.setCurrentStatus("未开始");
                    break;
                case 1:
                    l.setCurrentStatus("进行中");
                    break;
                case 2:
                    l.setCurrentStatus("待审核");
                    break;
                case 3:
                    l.setCurrentStatus("已完成");
                    break;
                case 4:
                    l.setCurrentStatus("驳回待处理");
                    break;
                default:
                    break;
            }

        }
        ExcelUtil<BizFinancialReceiveTicket> util = new ExcelUtil<BizFinancialReceiveTicket>(BizFinancialReceiveTicket.class);
        util.exportExcel(response, list, "收票任务数据");
    }

    /**
     * 获取收票任务详细信息
     */
    @PreAuthorize("@ss.hasPermi('business:receiveTicket:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return success(bizFinancialReceiveTicketService.getById(id));
    }

    /**
     * 新增收票任务
     */
    @PreAuthorize("@ss.hasPermi('business:receiveTicket:add')")
    @Log(title = "收票任务", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody BizFinancialReceiveTicket bizFinancialReceiveTicket) throws NoSuchFieldException, IllegalAccessException {
        setTenantId(bizFinancialReceiveTicket);
        return toAjax(bizFinancialReceiveTicketService.save(bizFinancialReceiveTicket));
    }

    /**
     * 修改收票任务
     */
    @PreAuthorize("@ss.hasPermi('business:receiveTicket:edit')")
    @Log(title = "收票任务", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody BizFinancialReceiveTicket bizFinancialReceiveTicket) throws NoSuchFieldException, IllegalAccessException {
        setTenantId(bizFinancialReceiveTicket);
        return toAjax(bizFinancialReceiveTicketService.updateById(bizFinancialReceiveTicket));
    }

    /**
     * 删除收票任务
     */
    @PreAuthorize("@ss.hasPermi('business:receiveTicket:remove')")
    @Log(title = "收票任务", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable List<Long> ids) {
        return toAjax(bizFinancialReceiveTicketService.removeBatchByIds(ids));
    }


    @PreAuthorize("@ss.hasPermi('business:receiveTicket:edit')")
    @PostMapping("/saveDetail")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult saveDetail(@RequestBody BizFinancialReceiveTicketDetail receiveTicketDetail) {
        // 判断之前是否有保存一个明细
        BizFinancialReceiveTicketDetail conditions = new BizFinancialReceiveTicketDetail();
        conditions.setFinancialReceiveTicketId(receiveTicketDetail.getFinancialReceiveTicketId());
        conditions.setYear(receiveTicketDetail.getYear());
        conditions.setMonth(receiveTicketDetail.getMonth());
        if (!financialReceiveTicketDetailService.getList(conditions).isEmpty()) {
            return error("该月已添加收票信息,请刷新列表。");
        }
        return toAjax(financialReceiveTicketDetailService.save(receiveTicketDetail) && addRecord(receiveTicketDetail.getFinancialReceiveTicketId(), receiveTicketDetail.getYear(), receiveTicketDetail.getMonth(), SecurityUtils.getUserId(), "填写收票信息"));
    }

    @PreAuthorize("@ss.hasPermi('business:receiveTicket:edit')")
    @PostMapping("/updateDetail")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult updateDetail(@RequestBody BizFinancialReceiveTicketDetail bizFinancialSalaryDetail) {
        return toAjax(financialReceiveTicketDetailService.updateById(bizFinancialSalaryDetail) && addRecord(bizFinancialSalaryDetail.getFinancialReceiveTicketId(), bizFinancialSalaryDetail.getYear(), bizFinancialSalaryDetail.getMonth(), SecurityUtils.getUserId(), "修改工资信息"));
    }


    @PreAuthorize("@ss.hasPermi('business:receiveTicket:verify')")
    @PostMapping("/verifyDetail")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult verifyDetail(@RequestBody BizFinancialReceiveTicketDetail detail) {
        detail.setVerifierId(SecurityUtils.getUserId());
        boolean bool = handleFeedback(detail);
        if (detail.getFeedbackStatus().equals(1)) {
            BizFinancialReceiveTicketFeedback financialReceiveTicketFeedback = new BizFinancialReceiveTicketFeedback();
            financialReceiveTicketFeedback
                    .setFinancialReceiveTicketId(detail.getFinancialReceiveTicketId())
                    .setFinancialReceiveTicketDetailId(detail.getId())
                    .setStatus(1)
                    .setTenantId(getTenantId())
                    .setCompanyId(detail.getCompanyId())
                    .setNeedSync(detail.getStatus().equals(4) ? 1 : 0);
            financialReceiveTicketFeedback.setRemark(detail.getFeedbackContent());
            financialReceiveTicketFeedbackService.save(financialReceiveTicketFeedback);
        }
        if (detail.getStatus().equals(3)) {
            bool = bool && checkKeepAccount(detail);
        }
        detail.setVerifierTime(new Date());
//        return bool && financialReceiveTicketDetailService.updateById(detail) ? Rutils.success() : Rutils.error();
        return toAjax(bool && financialReceiveTicketDetailService.updateById(detail));
    }

    @PreAuthorize("@ss.hasPermi('business:receiveTicket:return')")
    @PostMapping("/turnBackDetail")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult turnBackDetail(@RequestBody BizFinancialReceiveTicketDetail detail) {
        // 先判断是否记账完成，记账完成状态不能进行工资退回
        BizFinancialKeepAccountDetail keepAccountDetail = financialKeepAccountDetailService.query().eq("company_id", detail.getCompanyId()).eq("year", detail.getYear()).eq("month", detail.getMonth()).one();
        if (keepAccountDetail != null && keepAccountDetail.getStatus() == 3) {
            return error("请先进行记账退回操作再进行工资退回。");
        } else {
            detail.setStatus(2);
        }
        return toAjax(financialReceiveTicketDetailService.updateById(detail) && addRecord(detail.getFinancialReceiveTicketId(), detail.getYear(), detail.getMonth(), SecurityUtils.getUserId(), "收票退回"));
    }


    private boolean addRecord(Long financialReceiveTicketId, String year, String month, Long recorderId, String description) {
        // 没拆分合同单价
        BizFinancialReceiveTicket receiveTicket = bizFinancialReceiveTicketService.getById(financialReceiveTicketId);
        Long workOrderId = receiveTicket.getWorkOrderId();
        List<BizWorkOrderRecord> records = bizWorkOrderRecordService.query().eq("work_order_id", workOrderId).eq("year", year).eq("month", month).eq("from_id", 0).list();
        if (records.isEmpty()) {
            // 新增一条记录
            BizWorkOrderRecord record = new BizWorkOrderRecord();
            record.setMonth(month);
            record.setYear(year);
            record.setTenantId(getTenantId());
            record.setWorkOrderId(workOrderId);
            record.setCompanyId(receiveTicket.getCompanyId());
            record.setStatus(1);
            record.setStatusDescript(description);
            record.setRecorderId(recorderId);
            return bizWorkOrderRecordService.save(record);
        } else {
            // 新增一条子记录
            Long fromId = records.get(0).getId();
            BizWorkOrderRecord fromRecord = records.get(0);
            BizWorkOrderRecord record = new BizWorkOrderRecord();
            record.setFromId(fromId);
            record.setMonth(fromRecord.getMonth());
            record.setYear(fromRecord.getYear());
            record.setTenantId(fromRecord.getTenantId());
            record.setWorkOrderId(fromRecord.getWorkOrderId());
            record.setCompanyId(receiveTicket.getCompanyId());
            record.setStatus(fromRecord.getStatus());
            record.setStatusDescript(fromRecord.getStatusDescript());
            record.setRecorderId(fromRecord.getRecorderId());

            fromRecord.setMonth(month);
            fromRecord.setYear(year);
            fromRecord.setTenantId(getTenantId());
            fromRecord.setWorkOrderId(workOrderId);
            fromRecord.setCompanyId(receiveTicket.getCompanyId());
            fromRecord.setStatus(1);
            fromRecord.setStatusDescript(description);
            fromRecord.setRecorderId(recorderId);
            return bizWorkOrderRecordService.save(record) &&
                    bizWorkOrderRecordService.updateById(fromRecord);
        }
    }

    private boolean handleFeedback(BizFinancialReceiveTicketDetail detail) {
        // 判断是否有同步的反馈假设有则根据detail内容填写状态
        List<BizFinancialReceiveTicketFeedback> financialReceiveTicketFeedbacks = financialReceiveTicketFeedbackService.query().eq("financial_receive_ticket_detail_id", detail.getId()).eq("need_sync", 1).eq("status", 1).list();
        if (financialReceiveTicketFeedbacks.isEmpty()) {
            return true;
        } else {
            financialReceiveTicketFeedbacks.forEach(l -> {
                l.setFeedbackContent(getFeedbackContent(detail.getStatus()));
                l.setFeedbackTime(DateTime.now().toTimestamp());
                l.setStatus(detail.getStatus() >= 3 ? 2 : l.getStatus());
            });
            return financialReceiveTicketFeedbackService.saveOrUpdateBatch(financialReceiveTicketFeedbacks);
        }
    }


    private String getFeedbackContent(Integer status) {
        switch (status) {
            case 1:
                return "重新录入待确认";
            case 2:
                return "重新录入待审核";
            case 3:
                return "重新录入并完成";
            case 4:
                return "重新录入并驳回";
            default:
                return "";
        }
    }

    private Boolean checkKeepAccount(BizFinancialReceiveTicketDetail detail) {
        BizFinancialReceiveTicketDetail financialSalaryDetail = financialReceiveTicketDetailService.query().eq("company_id", detail.getCompanyId()).eq("year", detail.getYear()).eq("month", detail.getMonth()).one();
        if (financialSalaryDetail != null) {
            QueryWrapper<BizFinancialKeepAccount> qw = new QueryWrapper<>();
            qw.eq("company_id", detail.getCompanyId());
            qw.eq("is_stop", 0);
            BizFinancialKeepAccount financialKeepAccount = financialKeepAccountService.getOne(qw);
            if (financialKeepAccount != null) {
                QueryWrapper<BizFinancialKeepAccountDetail> kqw = new QueryWrapper<>();
                kqw.eq("financial_keep_account_id", financialKeepAccount.getId());
                kqw.eq("year", detail.getYear());
                kqw.eq("month", detail.getMonth());
                BizFinancialKeepAccountDetail financialKeepAccountDetail =
                        financialKeepAccountDetailService.getOne(kqw);
                if (financialKeepAccountDetail == null) {
                    financialKeepAccountDetail = new BizFinancialKeepAccountDetail();
                }
                financialKeepAccountDetail.setFinancialKeepAccountId(financialKeepAccount.getId());
                financialKeepAccountDetail.setYear(detail.getYear());
                financialKeepAccountDetail.setMonth(detail.getMonth());
                financialKeepAccountDetail.setCompanyId(detail.getCompanyId());
                List<BizFinancialSalaryDetailEmployee> employees = financialSalaryDetailEmployeeService.query().eq("financial_salary_detail_id", financialSalaryDetail.getId()).list();
                financialKeepAccountDetail.setStatus(detail.getSumNumber().equals(0) && ((employees.size() == 1 && employees.stream().mapToDouble(v -> v.getActuallySalary().doubleValue()).sum() == 0) || (employees.isEmpty())) ? 2 : 1);
//                financialKeepAccountDetail.setReceiveDate((Timestamp) detail.getReceiveDate());
                Date receiveDate = detail.getReceiveDate();
                if(receiveDate != null ){
                    Timestamp timestamp = new Timestamp(receiveDate.getTime());
                    financialKeepAccountDetail.setReceiveDate(timestamp);
                }
//                financialKeepAccountDetailService.saveOrUpdate(financialKeepAccountDetail);
                if (financialKeepAccountDetail.getId() == null) {
                    return financialKeepAccountDetailService.save(financialKeepAccountDetail);
                } else {
                    return financialKeepAccountDetailService.updateById(financialKeepAccountDetail);
                }
            }
        }
        return true;
    }
}
