package com.hz.pm.api.projectdeclared.manage;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.hz.pm.api.common.helper.UserInfoHelper;
import com.hz.pm.api.common.statemachine.util.StateMachineUtil;
import com.hz.pm.api.common.util.ExcelDownUtil;
import com.hz.pm.api.common.util.ExcelExportStyle;
import com.hz.pm.api.projectdeclared.model.dto.DeclaredProjectExportDTO;
import com.hz.pm.api.projectdeclared.model.dto.PurchaseSaveDTO;
import com.hz.pm.api.projectdeclared.model.entity.Purchase;
import com.hz.pm.api.projectdeclared.model.vo.PurchaseVO;
import com.hz.pm.api.projectdeclared.service.IPurchaseService;
import com.hz.pm.api.projectlib.helper.ProjectHelper;
import com.hz.pm.api.projectlib.model.entity.Project;
import com.hz.pm.api.projectlib.model.enumeration.ProjectStatusEnum;
import com.hz.pm.api.projectlib.model.enumeration.ProjectTypeNewEnum;
import com.hz.pm.api.projectlib.model.req.ProjectListReq;
import com.hz.pm.api.projectlib.model.vo.ProjectLibListItemVO;
import com.hz.pm.api.projectlib.service.IProjectService;
import com.hz.pm.api.user.security.model.UserFullInfoDTO;
import com.hz.pm.api.user.util.LoginUserUtil;
import com.ningdatech.basic.exception.BizException;
import com.ningdatech.basic.function.VUtils;
import com.ningdatech.basic.model.PageVo;
import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.basic.util.NdDateUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Classname PurchaseManage
 * @Description
 * @Date 2023/5/29 14:48
 * @Author PoffyZhang
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class PurchaseManage {

    private final IProjectService projectService;
    private final UserInfoHelper userInfoHelper;

    private final IPurchaseService purchaseService;

    private final StateMachineUtil stateMachineUtil;

    /**
     * 待采购的-项目列表
     *
     * @param req
     * @return
     */
    public PageVo<ProjectLibListItemVO> projectLibList(ProjectListReq req) {
        UserFullInfoDTO user = userInfoHelper.getUserFullInfo(LoginUserUtil.getUserId());
        Assert.notNull(user, "获取登录用户失败!");
        LambdaQueryWrapper<Project> query = ProjectHelper.projectQuery(req);
        //只能看自己单位的
        query.eq(Project::getBuildOrgCode, user.getMhUnitIdStr());
        //待采购状态
        query.in(Project::getStatus, Lists.newArrayList(ProjectStatusEnum.TO_BE_PURCHASED.getCode(),
                ProjectStatusEnum.OPERATION.getCode()));
        query.eq(Project::getStage, ProjectStatusEnum.PROJECT_APPROVED.getCode());
        query.eq(Project::getNewest, Boolean.TRUE);
        query.orderByAsc(Project::getApprovalDate);
        Page<Project> page = projectService.page(req.page(), query);
        long total;
        if ((total = page.getTotal()) == 0) {
            return PageVo.empty();
        }
        List<ProjectLibListItemVO> records = CollUtils.convert(page.getRecords(), w -> {
            ProjectLibListItemVO item = new ProjectLibListItemVO();
            item.setId(w.getId());
            item.setProjectName(w.getProjectName());
            item.setCreateOn(w.getCreateOn());
            item.setDeclaredAmount(w.getDeclareAmount());
            item.setStage(w.getStage());
            item.setStatus(w.getStatus());
            item.setProjectType(w.getProjectType());
            item.setProjectYear(w.getProjectYear());
            item.setBuildOrg(w.getBuildOrgName());
            item.setBizDomain(w.getBizDomain());
            item.setProcessStatus(w.getProcessStatus());
            item.setInstCode(w.getInstCode());
            item.setIsHigherSuperOrg(w.getIsHigherSuperOrg());
            item.setApprovedAmount(w.getApprovalAmount());
            item.setApprovalDate(w.getApprovalDate());
            return item;
        });
        return PageVo.of(records, total);
    }

    public void exportList(HttpServletResponse response, ProjectListReq param) {
        UserFullInfoDTO user = userInfoHelper.getUserFullInfo(LoginUserUtil.getUserId());
        VUtils.isTrue(Objects.isNull(user)).throwMessage("获取登录用户失败!");
        LambdaQueryWrapper<Project> query = ProjectHelper.projectQuery(param);
        //待采购状态
        //只能看自己单位的
        query.eq(Project::getBuildOrgCode, user.getMhUnitId());
        query.eq(Project::getStatus, ProjectStatusEnum.TO_BE_PURCHASED.getCode());
        query.eq(Project::getStage, ProjectStatusEnum.PROJECT_APPROVED.getCode());
        query.eq(Project::getNewest, Boolean.TRUE);
        query.orderByAsc(Project::getApprovalDate);
        List<Project> records = projectService.list(query);
        Assert.notEmpty(records, "暂无数据可导出");
        List<DeclaredProjectExportDTO> data = Lists.newArrayList();

        AtomicInteger serialNumber = new AtomicInteger(0);
        records.forEach(r -> {
            DeclaredProjectExportDTO dpe = new DeclaredProjectExportDTO();
            BeanUtils.copyProperties(r, dpe);
            dpe.setProjectTypeName(ProjectTypeNewEnum.getDesc(r.getProjectType()));
            dpe.setStatusName(ProjectStatusEnum.getDesc(r.getStatus()));
            String createOnStr = NdDateUtils.format(r.getCreateOn(), "yyyy-MM-dd HH:mm");
            dpe.setCreateOn(createOnStr);
            dpe.setSerialNumber(serialNumber.incrementAndGet());
            dpe.setApprovedAmount(r.getApprovalAmount());
            dpe.setApprovalDate(r.getApprovalDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            data.add(dpe);
        });

        String fileName = "采购结果待备案项目列表";
        ExcelDownUtil.setFileName(fileName, response);
        //数据导出处理函数
        try {
            EasyExcel.write(response.getOutputStream(), DeclaredProjectExportDTO.class)
                    .autoCloseStream(false)
                    .registerWriteHandler(ExcelExportStyle.formalStyle())
                    .sheet(fileName)
                    .doWrite(data);
        } catch (IOException e) {
            log.error("导出异常", e);
            throw BizException.wrap("导出失败，请重试");
        }
    }

    /**
     * 获取采购结果备案详情
     *
     * @param projectId
     * @return
     */
    public List<PurchaseVO> detailByProjectId(Long projectId) {
        List<Purchase> purchases = purchaseService.listByProjectId(projectId);
        return BeanUtil.copyToList(purchases, PurchaseVO.class);
    }

    /**
     * 填写采购结果
     *
     * @param dto
     * @return
     */
    public String submitResult(PurchaseSaveDTO dto) {
        UserFullInfoDTO user = userInfoHelper.getUserFullInfo(LoginUserUtil.getUserId());
        Long projectId = dto.getProjectId();
        VUtils.isTrue(Objects.isNull(projectId)).throwMessage("提交失败 缺少项目ID!");
        Project project = projectService.getNewProject(dto.getProjectId());
        VUtils.isTrue(Objects.isNull(project)).throwMessage("提交失败 此项目不存在!");

        //首先要判断 项目当前状态 是不是 采购结果备案
        VUtils.isTrue(!ProjectStatusEnum.TO_BE_PURCHASED.eq(project.getStatus())
                        || !ProjectStatusEnum.PROJECT_APPROVED.eq(project.getStage()))
                .throwMessage("提交失败 该项目不是 待采购备案状态或者已立项阶段");

        List<Purchase> purchases = purchaseService.listByProjectId(projectId);
        Map<Long, Purchase> purchaseMap = CollUtils.listToMap(purchases, Purchase::getId);
        List<Purchase> purchaseEntities = CollUtils.convert(dto.getTenders(), w -> {
            Purchase purchase = BeanUtil.copyProperties(w, Purchase.class);
            purchase.setProjectId(projectId);
            if (!purchaseMap.containsKey(w.getId())) {
                purchase.setCreateBy(user.getUserIdStr());
            }
            return purchase;
        });

        if (purchaseService.saveOrUpdateBatch(purchaseEntities)) {
            stateMachineUtil.pass(project);
            project.setUpdateOn(LocalDateTime.now());

            // 获取总的成交时间及金额
            LocalDateTime lastTransactionTime = null;
            BigDecimal transactionAmountTotal = BigDecimal.ZERO;
            for (Purchase purchase : purchaseEntities) {
                if (lastTransactionTime == null || purchase.getTransactionTime().isAfter(lastTransactionTime)) {
                    lastTransactionTime = purchase.getTransactionTime();
                }
                transactionAmountTotal = transactionAmountTotal.add(purchase.getTransactionAmount());
            }

            project.setTransactionAmount(transactionAmountTotal);
            project.setTransactionTime(lastTransactionTime);
            projectService.updateById(project);

            return "填写成功";
        }

        return "保存失败";
    }

}
