package com.greenorange.promotion.controller.projectSettlement;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.greenorange.promotion.annotation.RequiresPermission;
import com.greenorange.promotion.annotation.SysLog;
import com.greenorange.promotion.common.BaseResponse;
import com.greenorange.promotion.common.ResultUtils;
import com.greenorange.promotion.constant.UserConstant;
import com.greenorange.promotion.model.dto.CommonRequest;
import com.greenorange.promotion.model.dto.projectSettlement.ProjectSettlementAddRequest;
import com.greenorange.promotion.model.entity.*;
import com.greenorange.promotion.model.vo.projectSettlement.MiniProjectSettlementVO;
import com.greenorange.promotion.model.vo.projectSettlement.ProjectSettlementVO;
import com.greenorange.promotion.service.common.CommonService;
import com.greenorange.promotion.service.project.ProjectDetailService;
import com.greenorange.promotion.service.project.PromoCodeApplyService;
import com.greenorange.promotion.service.project.SubUserProjectCommissionService;
import com.greenorange.promotion.service.settle.FundsChangeService;
import com.greenorange.promotion.service.settle.ProjectSettlementService;
import com.greenorange.promotion.service.userInfo.UserInfoService;
import com.greenorange.promotion.service.userInfo.UserMainInfoService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;


/**
 * 项目结算记录 控制器
 */
@RestController
@RequestMapping("projectSettlement")
@Slf4j
@Tag(name = "项目结算记录管理")
@Transactional
public class ProjectSettlementController {

    @Resource
    private ProjectSettlementService projectSettlementService;

    @Resource
    private FundsChangeService fundsChangeService;

    @Resource
    private CommonService commonService;

    @Resource
    private PromoCodeApplyService promoCodeApplyService;

    @Resource
    private UserMainInfoService userMainInfoService;

    @Resource
    private UserInfoService userInfoService;

    @Resource
    private ProjectDetailService projectDetailService;

    @Resource
    private SubUserProjectCommissionService subUserProjectCommissionService;




    /**
     * 小程序端用户根据推广码申请记录id查询结算记录
     * @param commonRequest 项目结算记录添加请求体
     * @return 是否添加成功
     */
    @PostMapping("query/settle")
    @Operation(summary = "小程序端用户根据推广码申请记录id查询结算记录", description = "参数：项目结算记录添加请求体，权限：管理员，方法名：queryProjectSettlementRecordByPid")
    @RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
//    @SysLog(title = "项目结算记录管理", content = "小程序端用户根据推广码申请记录id查询结算记录")
    public BaseResponse<List<MiniProjectSettlementVO>> queryProjectSettlementRecordByPid(@Valid @RequestBody CommonRequest commonRequest) {
        Long id = commonRequest.getId();
        Map<SFunction<ProjectSettlement, ?>, Object> fieldConditions = Map.of(ProjectSettlement::getPromoCodeApplyId, id);
        List<ProjectSettlement> projectSettlementList = commonService.findByFieldEqTargetFields(fieldConditions, projectSettlementService);
        List<PromoCodeApply> promoCodeApplyList = commonService.findByFieldInTargetFieldWithSpecificFields(projectSettlementList, promoCodeApplyService, ProjectSettlement::getPromoCodeApplyId, PromoCodeApply::getId,
                List.of(PromoCodeApply::getId, PromoCodeApply::getSalespersonName));
        // 封装Map集合（键：推广码申请记录id, 值：业务员姓名）
        Map<Long, String> salespersonNameMap = new HashMap<>();
        for (PromoCodeApply promoCodeApply : promoCodeApplyList) {
            salespersonNameMap.put(promoCodeApply.getId(), promoCodeApply.getSalespersonName());
        }
        List<MiniProjectSettlementVO> miniProjectSettlementVOList = commonService.convertList(projectSettlementList, MiniProjectSettlementVO.class);
        for (MiniProjectSettlementVO miniProjectSettlementVO : miniProjectSettlementVOList) {
            Long applyId = miniProjectSettlementVO.getPromoCodeApplyId();
            String salespersonName = salespersonNameMap.get(applyId);
            miniProjectSettlementVO.setSalespersonName(salespersonName);
        }
        return ResultUtils.success(miniProjectSettlementVOList);
    }

    /**
     * 小程序端用户查询当前推广项目的所有结算明细
     * @param commonRequest 项目id
     * @return 是否添加成功
     */
    @PostMapping("query/all/settle")
    @Operation(summary = "小程序端用户查询当前推广项目的所有结算明细", description = "参数：项目结算记录添加请求体，权限：管理员，方法名：queryProjectSettlementRecordByProjectId")
    @RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
//    @SysLog(title = "项目结算记录管理", content = "小程序端用户查询当前推广项目的所有结算明细")
    public BaseResponse<List<MiniProjectSettlementVO>> queryProjectSettlementRecordByProjectId(@Valid @RequestBody CommonRequest commonRequest, HttpServletRequest request) {
        Long projectId = commonRequest.getId();
        Long userId = (Long) request.getAttribute("userId");
        Map<SFunction<ProjectSettlement, ?>, Object> fieldConditions = Map.of(ProjectSettlement::getUserId, userId, ProjectSettlement::getProjectId, projectId);
        List<ProjectSettlement> projectSettlementList = commonService.findByFieldEqTargetFields(fieldConditions, projectSettlementService);
        List<PromoCodeApply> promoCodeApplyList = commonService.findByFieldInTargetFieldWithSpecificFields(projectSettlementList, promoCodeApplyService, ProjectSettlement::getPromoCodeApplyId, PromoCodeApply::getId,
                List.of(PromoCodeApply::getId, PromoCodeApply::getSalespersonName));
        // 封装Map集合（键：推广码申请记录id, 值：业务员姓名）
        Map<Long, String> salespersonNameMap = new HashMap<>();
        for (PromoCodeApply promoCodeApply : promoCodeApplyList) {
            salespersonNameMap.put(promoCodeApply.getId(), promoCodeApply.getSalespersonName());
        }
        List<MiniProjectSettlementVO> miniProjectSettlementVOList = commonService.convertList(projectSettlementList, MiniProjectSettlementVO.class);
        for (MiniProjectSettlementVO miniProjectSettlementVO : miniProjectSettlementVOList) {
            Long applyId = miniProjectSettlementVO.getPromoCodeApplyId();
            String salespersonName = salespersonNameMap.get(applyId);
            miniProjectSettlementVO.setSalespersonName(salespersonName);
        }
        return ResultUtils.success(miniProjectSettlementVOList);
    }

    /**
     * web端管理员添加项目结算记录
     * @param projectSettlementAddRequest 项目结算记录添加请求体
     * @return 是否添加成功
     */
    @PostMapping("add")
    @Transactional(rollbackFor = Exception.class)
    @Operation(summary = "web端管理员添加项目结算记录", description = "参数：项目结算记录添加请求体，权限：管理员，方法名：addProjectSettlement")
    @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
//    @SysLog(title = "项目结算记录管理", content = "web端管理员添加项目结算记录")
    public BaseResponse<Boolean> addProjectSettlement(@Valid @RequestBody ProjectSettlementAddRequest projectSettlementAddRequest) {
        // 添加当前用户的项目结算记录
        ProjectSettlement projectSettlement = commonService.copyProperties(projectSettlementAddRequest, ProjectSettlement.class);
        // 根据项目名称获取项目明细id
        String projectDetailName = projectSettlement.getProjectDetailName();
        Long projectId = projectSettlement.getProjectId();
        Map<SFunction<ProjectDetail, ?>, Object> fieldConditions = Map.of(ProjectDetail::getProjectId, projectId, ProjectDetail::getProjectDetailName, projectDetailName);
        List<ProjectDetail> projectDetails = commonService.findByFieldEqTargetFields(fieldConditions, projectDetailService);
        ProjectDetail proDetail = projectDetails.get(0);
        projectSettlement.setProjectDetailId(proDetail.getId());
        projectSettlementService.save(projectSettlement);

        Long userId = projectSettlement.getUserId();
        LambdaQueryWrapper<UserMainInfo> userMainInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userMainInfoLambdaQueryWrapper.eq(UserMainInfo::getUserId, userId);
        UserMainInfo userMainInfo = userMainInfoService.getOne(userMainInfoLambdaQueryWrapper);
        BigDecimal currentBalance = userMainInfo.getCurrentBalance();
        // 获取项目结算记录的参数
        BigDecimal settlementRevenue = projectSettlement.getSettlementRevenue();
        Long projectSettlementId = projectSettlement.getId();
        // 获取项目明细的结算价格
        Long projectDetailId = projectSettlement.getProjectDetailId();
        ProjectDetail projectDetail = projectDetailService.getById(projectDetailId);
        BigDecimal projectMinSettlementPrice = projectDetail.getProjectMinSettlementPrice();
        // 批量添加上级用户的项目结算记录
        List<SubUserProjectCommission> subUserProjectCommissionList = commonService.findByFieldEqTargetField(SubUserProjectCommission::getProjectDetailId, projectDetailId, subUserProjectCommissionService);
        // 封装Map集合（键：用户id-下级用户id，值：抽佣价格）
        Map<String, BigDecimal> subUserProjectCommissionMap = new HashMap<>();
        for (SubUserProjectCommission subUserProjectCommission : subUserProjectCommissionList) {
            Long uid = subUserProjectCommission.getUserId();
            Long subUid = subUserProjectCommission.getSubUserId();
            BigDecimal myUnitPrice = subUserProjectCommission.getMyUnitPrice();
            BigDecimal currentCommissionRate = subUserProjectCommission.getCurrentCommissionRate();
            BigDecimal agentUnitPrice = myUnitPrice.multiply(BigDecimal.ONE.subtract(currentCommissionRate.divide(BigDecimal.valueOf(100))));
            if (agentUnitPrice.compareTo(projectMinSettlementPrice) <= 0) agentUnitPrice = projectMinSettlementPrice;
            subUserProjectCommissionMap.put(uid + "-" + subUid, myUnitPrice.subtract(agentUnitPrice));
        }
        List<ProjectSettlement> projectSettlementList = new ArrayList<>();
        // 获取当前用户到根用户的路径
        List<Long> pathToRoot = userInfoService.findPathToRoot(userId);
        for (int i = 0; i < pathToRoot.size() - 1; i ++ ) {
            Long uid = pathToRoot.get(i);
            Long subUid = pathToRoot.get(i + 1);
            BigDecimal commissionRatePrice = subUserProjectCommissionMap.get(uid + "-" + subUid);
            if (commissionRatePrice.compareTo(BigDecimal.ZERO) == 0) continue;
            ProjectSettlement projectSettle = commonService.copyProperties(projectSettlementAddRequest, ProjectSettlement.class);
            projectSettle.setProjectDetailId(projectDetailId);
            projectSettle.setSettlementRevenue(commissionRatePrice);
            projectSettle.setRevenueSource(true);
            projectSettle.setSuperId(projectSettlementId);
            projectSettle.setUserId(uid);
            projectSettlementList.add(projectSettle);
        }
        projectSettlementService.saveBatch(projectSettlementList);

        // 添加当前用户的资金变动记录
        FundsChange fundsChange = FundsChange.builder()
                .projectName(projectSettlement.getProjectDetailName())
                .changeAmount(settlementRevenue)
                .currentAmount(currentBalance.add(settlementRevenue))
                .userId(userId)
                .projectSettlementId(projectSettlementId)
                .build();
        fundsChangeService.save(fundsChange);

        // 获取用户主要信息
        List<UserMainInfo> userMainInfoList = commonService.findByFieldInTargetFieldWithSpecificFields(pathToRoot, userMainInfoService, Function.identity(), UserMainInfo::getUserId,
                List.of(UserMainInfo::getUserId, UserMainInfo::getCurrentBalance));
        // 封装Map集合（键：用户id，值：用户余额）
        Map<Long, BigDecimal> userMainInfoMap = new HashMap<>();
        for (UserMainInfo mainInfo : userMainInfoList) {
            userMainInfoMap.put(mainInfo.getUserId(), mainInfo.getCurrentBalance());
        }

        // 批量添加上级用户的项目结算记录
        List<FundsChange> fundsChangeList = new ArrayList<>();
        for (ProjectSettlement projectSettle : projectSettlementList) {
            // 取出当前用户的余额
            Long uid = projectSettle.getUserId();
            BigDecimal currentAmount = userMainInfoMap.get(uid);
            FundsChange funds = FundsChange.builder()
                    .projectName(projectSettle.getProjectDetailName())
                    .changeAmount(projectSettle.getSettlementRevenue())
                    .currentAmount(currentAmount.add(projectSettle.getSettlementRevenue()))
                    .userId(uid)
                    .projectSettlementId(projectSettle.getId())
                    .build();
            fundsChangeList.add(funds);
        }
        fundsChangeService.saveBatch(fundsChangeList);

        return ResultUtils.success(true);
    }

//    /**
////     * web端管理员根据id修改项目结算记录信息
////     * @param projectSettlementUpdateRequest 项目结算记录更新请求体
////     * @return 是否更新成功
////     */
////    @PostMapping("update")
////    @Operation(summary = "web端管理员根据id修改项目结算记录信息", description = "参数：项目结算记录更新请求体，权限：管理员，方法名：updateProjectSettlement")
////    @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
////    @SysLog(title = "项目结算记录管理", content = "web端管理员根据id修改项目结算记录信息")
////    public BaseResponse<Boolean> updateProjectSettlement(@Valid @RequestBody ProjectSettlementUpdateRequest projectSettlementUpdateRequest) {
////        ProjectSettlement projectSettlement = commonService.copyProperties(projectSettlementUpdateRequest, ProjectSettlement.class);
////        projectSettlementService.updateById(projectSettlement);
////        // 修改资金变动记录
////        Long id = projectSettlement.getId();
////        LambdaQueryWrapper<FundsChange> lambdaQueryWrapper = new LambdaQueryWrapper<>();
////        lambdaQueryWrapper.eq(FundsChange::getProjectSettlementId, id);
////        FundsChange fundsChange = fundsChangeService.getOne(lambdaQueryWrapper);
////        BigDecimal changeAmount = fundsChange.getChangeAmount();
////        BigDecimal currentAmount = fundsChange.getCurrentAmount();
////        BigDecimal originAmount = currentAmount.subtract(changeAmount);
////        fundsChange.setChangeAmount(projectSettlement.getSettlementRevenue());
////        fundsChange.setCurrentAmount(originAmount.add(projectSettlement.getSettlementRevenue()));
////        fundsChangeService.updateById(fundsChange);
////        return ResultUtils.success(true);
////    }

    /**
     * web端管理员根据id删除项目结算记录
     * @param commonRequest 项目结算记录删除请求体
     * @return 是否删除成功
     */
    @PostMapping("delete")
    @Operation(summary = "web端管理员根据id删除项目结算记录", description = "参数：项目结算记录删除请求体，权限：管理员，方法名：delProjectSettlement")
    @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
//    @SysLog(title = "项目结算记录管理", content = "web端管理员根据id删除项目结算记录")
    public BaseResponse<Boolean> delProjectSettlement(@Valid @RequestBody CommonRequest commonRequest) {
        Long id = commonRequest.getId();
        projectSettlementService.removeById(id);
        // 删除资金变动记录
        LambdaQueryWrapper<FundsChange> lambdaQueryWrapper = commonService.buildQueryWrapperByField(FundsChange::getProjectSettlementId, id, fundsChangeService);
        fundsChangeService.remove(lambdaQueryWrapper);
        return ResultUtils.success(true);
    }

//    /**
//     * web端管理员批量删除项目结算记录
//     * @param commonBatchRequest 项目结算记录批量删除请求体
//     * @return 是否删除成功
//     */
//    @PostMapping("delBatch")
//    @Operation(summary = "web端管理员批量删除项目结算记录", description = "参数：项目结算记录批量删除请求体，权限：管理员，方法名：delBatchProjectSettlement")
//    @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
//    @SysLog(title = "项目结算记录管理", content = "web端管理员批量删除项目结算记录")
//    public BaseResponse<Boolean> delBatchProjectSettlement(@Valid @RequestBody CommonBatchRequest commonBatchRequest) {
//        List<Long> ids = commonBatchRequest.getIds();
//        projectSettlementService.removeByIds(ids);
//        return ResultUtils.success(true);
//    }

    /**
     * web端管理员根据id查询项目结算记录
     * @param commonRequest 项目结算记录查询请求体
     * @return 项目结算记录信息
     */
    @PostMapping("queryById")
    @Operation(summary = "web端管理员根据id查询项目结算记录", description = "参数：项目结算记录查询请求体，权限：管理员，方法名：queryProjectSettlementById")
    @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
//    @SysLog(title = "项目结算记录管理", content = "web端管理员根据id查询项目结算记录")
    public BaseResponse<ProjectSettlementVO> queryProjectSettlementById(@Valid @RequestBody CommonRequest commonRequest) {
        Long id = commonRequest.getId();
        ProjectSettlement projectSettlement = projectSettlementService.getById(id);
        ProjectSettlementVO projectSettlementVO = commonService.copyProperties(projectSettlement, ProjectSettlementVO.class);
        return ResultUtils.success(projectSettlementVO);
    }


    /**
     * Web端管理员根据推广码申请记录id查询项目结算记录列表
     * @param commonRequest 推广码申请记录id
     * @return 项目结算记录列表
     */
    @PostMapping("queryByPId")
    @Operation(summary = "Web端管理员根据推广码申请记录id查询项目结算记录列表", description = "参数：推广码申请记录id，权限：管理员，方法名：queryProjectSettlementByPid")
    @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
//    @SysLog(title = "项目结算记录管理", content = "Web端管理员根据推广码申请记录id查询项目结算记录列表")
    public BaseResponse<List<ProjectSettlementVO>> queryProjectSettlementByPid(@Valid @RequestBody CommonRequest commonRequest) {
        Long id = commonRequest.getId();
        List<ProjectSettlement> projectSettlementList = commonService.findByFieldEqTargetField(ProjectSettlement::getPromoCodeApplyId, id, projectSettlementService);
        List<ProjectSettlementVO> projectSettlementVOS = commonService.convertList(projectSettlementList, ProjectSettlementVO.class);
        return ResultUtils.success(projectSettlementVOS);
    }



//    /**
//     * Web端管理员分页查询项目结算记录
//     * @param projectSettlementQueryRequest 项目结算记录查询请求体
//     * @return 项目结算记录列表
//     */
//    @PostMapping("page")
//    @Operation(summary = "Web端管理员分页查询项目结算记录", description = "参数：项目结算记录查询请求体，权限：管理员，方法名：listProjectSettlementByPage")
//    @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
//    @SysLog(title = "项目结算记录管理", content = "Web端管理员分页查询项目结算记录")
//    public BaseResponse<Page<ProjectSettlementVO>> listProjectSettlementByPage(@Valid @RequestBody ProjectSettlementQueryRequest projectSettlementQueryRequest) {
//        long current = projectSettlementQueryRequest.getCurrent();
//        long pageSize = projectSettlementQueryRequest.getPageSize();
//        QueryWrapper<ProjectSettlement> queryWrapper = projectSettlementService.getQueryWrapper(projectSettlementQueryRequest);
//        Page<ProjectSettlement> page = projectSettlementService.page(new Page<>(current, pageSize), queryWrapper);
//        List<ProjectSettlement> projectSettlementList = page.getRecords();
//        List<ProjectSettlementVO> projectSettlementVOList = commonService.convertList(projectSettlementList, ProjectSettlementVO.class);
//        Page<ProjectSettlementVO> voPage = new Page<>(current, pageSize);
//        voPage.setRecords(projectSettlementVOList);
//        voPage.setPages(page.getPages());
//        voPage.setTotal(page.getTotal());
//        return ResultUtils.success(voPage);
//    }
}