package cn.iocoder.yudao.module.system.service.biz;

import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ContractPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ElderlyContractResVO;
import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ElderlyContractVO;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.*;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
import cn.iocoder.yudao.module.system.dal.mysql.biz.*;
import cn.iocoder.yudao.module.system.enums.common.BooleanEnum;
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class ElderlyContractServiceImpl implements ElderlyContractService {

    @Resource
    private BuildService buildService;
    @Resource
    private TenantService tenantService;
    @Resource
    private ExpenseMapper expenseMapper;
    @Resource
    private ElderlyInfoMapper elderlyInfoMapper;
    @Resource
    private ExpenseItemMapper expenseItemMapper;
    @Resource
    private ElderlyContractMapper elderlyContractMapper;
    @Resource
    private ElderlyChangeRecordMapper elderlyChangeRecordMapper;
    @Resource
    private ElderlyContractDetailMapper elderlyContractDetailMapper;
    @Resource
    private ElderlySyntheticAbilityMapper elderlySyntheticAbilityMapper;

    @Resource
    private PriceChangeRecordMapper priceChangeRecordMapper;
    @Resource
    private DepositRecordMapper depositRecordMapper;


    @Override
    public Long createContract(ElderlyContractDO contractDO) {
        contractDO.setCreatedTime(new Date());
        elderlyContractMapper.insert(contractDO);

        List<ElderlyContractDetailDO> details = contractDO.getDetails();
        if (null ==  details) return contractDO.getId();
        for (ElderlyContractDetailDO detail : details) {
            detail.setContractId(contractDO.getId());
            detail.setCreateDate(LocalDateTime.now());
            elderlyContractDetailMapper.insert(detail);
        }
        return contractDO.getId();
    }

    @Override
    public PageResult<ElderlyContractDO> findPage(ContractPageReqVO reqVO) {
        Page<ElderlyContractDO> page = new Page<>(reqVO.getPageNo(), reqVO.getPageSize());
        List<ElderlyContractDO> list = elderlyContractMapper.findPage(page, reqVO);
        Date currentDate = new Date();
        for (ElderlyContractDO elderlyContractDO : list) {
            TenantDO tenant = tenantService.getTenant(elderlyContractDO.getTenantId());
            elderlyContractDO.setTenantName(tenant == null ? null : tenant.getName());

            if (elderlyContractDO.getBeginTime().after(currentDate)) {
                // 合同未开始
                elderlyContractDO.setStatus(2);
            } else if (elderlyContractDO.getExpireTime().before(currentDate)) {
                // 合同已过期
                elderlyContractDO.setStatus(0);
            } else {
                // 合同正在进行中
                elderlyContractDO.setStatus(1);
            }
        }
        return new PageResult<>(list, page.getTotal());
    }

    @Override
    public ElderlyContractVO getContract(Long id) {
        ElderlyContractVO elderlyContractVO = new ElderlyContractVO();
        ElderlyContractDO elderlyContract = elderlyContractMapper.selectById(id);
        if (elderlyContract != null) {
            BeanUtils.copyProperties(elderlyContract, elderlyContractVO);
            ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(elderlyContract.getElderId());
            elderlyContractVO.setElderName(elderlyInfo.getElderName());
            elderlyContractVO.setElderTags(StringUtils.isBlank(elderlyInfo.getElderTags()) ? null : elderlyInfo.getElderTags());
            elderlyContractVO.setNursingLevelName(elderlyInfo.getNurseLevelName());
            elderlyContractVO.setBedName(buildService.getFullBedName(elderlyInfo.getId()));
            elderlyContractVO.setSpecialCareNotes(elderlyInfo.getSpecialCareNotes());
            elderlyContractVO.setContractNumber(elderlyContract.getContractNumber());
            elderlyContractVO.setNursingLevelId(elderlyInfo.getNurseLevelId());
            elderlyContractVO.setContractTerm(elderlyContract.getContractTerm());

            List<ElderlySyntheticAbilityDO> elderlySyntheticAbilityList = elderlySyntheticAbilityMapper
                    .selectList(new LambdaQueryWrapperX<ElderlySyntheticAbilityDO>()
                            .eq(ElderlySyntheticAbilityDO::getElderId, elderlyInfo.getId()));

            if (CollectionUtil.isNotEmpty(elderlySyntheticAbilityList)) {
                ElderlySyntheticAbilityDO elderlySyntheticAbilityDO = elderlySyntheticAbilityList
                        .stream()
                        .filter(item -> item.getEvaluationAgency().equals("1"))
                        .findFirst()
                        .get();

                if (elderlySyntheticAbilityDO != null) {
                    elderlyContractVO.setSyntheticAbilityResult(elderlySyntheticAbilityDO.getResult());
                }
            }

            //查询附件
            List<ElderlyContractDetailDO> elderlyContractDetails = elderlyContractDetailMapper.selectList(new LambdaQueryWrapperX<ElderlyContractDetailDO>()
                    .eq(ElderlyContractDetailDO::getContractId, elderlyContract.getId()));
            elderlyContractVO.setDetails(elderlyContractDetails);

            Optional<ExpenseDO> optional = expenseMapper.selectList(new LambdaQueryWrapperX<ExpenseDO>()
                            .eq(ExpenseDO::getElderId, elderlyInfo.getId()).orderByDesc(ExpenseDO::getCreatedTime))
                    .stream()
                    .findFirst();


            if (optional.isPresent()) {
                ExpenseDO expenseDO = optional.get();
                List<ExpenseItemDO> expenseItems = expenseItemMapper.selectList(new LambdaQueryWrapperX<ExpenseItemDO>()
                        .eq(ExpenseItemDO::getExpenseId, expenseDO.getId()));

                for (ExpenseItemDO expenseItem : expenseItems) {
                    if (expenseItem.getType() != null) {
                        if (expenseItem.getType() == 1) {
                            //床位费
                            elderlyContractVO.setBedAmount(expenseItem.getActualAmount());
                            elderlyContractVO.setBedItemName(expenseItem.getItemName());
                        } else if (expenseItem.getType() == 2) {
                            //护理费
                            elderlyContractVO.setNurseAmount(expenseItem.getActualAmount());
                        } else if (expenseItem.getType() == 3) {
                            //膳食费
                            elderlyContractVO.setMealAmount(expenseItem.getActualAmount());
                            elderlyContractVO.setMealItemName(expenseItem.getItemName());
                        }
                    }
                }
            }
        }
        return elderlyContractVO;
    }

//    @Override
//    public ElderlyContractResVO getContractByElderId(Long elderId) {
//        ElderlyContractResVO resVO = new ElderlyContractResVO();
//
//        ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(elderId);
//        resVO.setElderName(elderlyInfo.getElderName());
//        resVO.setElderTags(elderlyInfo.getElderTags());
//        resVO.setBedName(buildService.getFullBedName(elderId));
//        resVO.setCheckInTime(elderlyInfo.getCheckInTime());
//        resVO.setNursingLevelName(elderlyInfo.getNurseLevelName());
//        resVO.setSpecialCareNotes(elderlyInfo.getSpecialCareNotes());
//
//
//        Optional<ExpenseDO> optional = expenseMapper.selectList(new LambdaQueryWrapperX<ExpenseDO>()
//                        .eq(ExpenseDO::getElderId, elderlyInfo.getId())
//                        .orderByDesc(ExpenseDO::getCreatedTime))
//                .stream()
//                .findFirst();
//
//        if (optional.isPresent()) {
//            ExpenseDO expenseDO = optional.get();
//            List<ExpenseItemDO> expenseItems = expenseItemMapper.selectList(new LambdaQueryWrapperX<ExpenseItemDO>()
//                    .eq(ExpenseItemDO::getExpenseId, expenseDO.getId()));
////            resVO.setAmount(expenseDO.getTotalAmount());
//            resVO.setExpenseItems(expenseItems);
//        }
//
//
//        List<ElderlyContractDO> elderlyContractList = elderlyContractMapper.selectList(new LambdaQueryWrapperX<ElderlyContractDO>()
//                .eq(ElderlyContractDO::getElderId, elderlyInfo.getId())
//                .orderByDesc(ElderlyContractDO::getCreatedTime));
//
//
//
//        if (CollectionUtil.isNotEmpty(elderlyContractList)) {
//            ElderlyContractDO elderlyContractDO = elderlyContractList.stream().findFirst().get();
////            resVO.setContractNumber(elderlyContractDO.getContractNumber());
////            resVO.setBeginTime(elderlyContractDO.getBeginTime());
////            resVO.setExpireTime(elderlyContractDO.getExpireTime());
////            resVO.setContractTerm(elderlyContractDO.getContractTerm());
//
//
//            //附件列表
//            List<ElderlyContractDetailDO> elderlyContractDetails = elderlyContractDetailMapper.selectList(new LambdaQueryWrapperX<ElderlyContractDetailDO>()
//                    .eq(ElderlyContractDetailDO::getContractId, elderlyContractDO.getId()));
//
//            resVO.setContractDetails(elderlyContractDetails);
//        }
//        resVO.setExpenseItems(resVO.getExpenseItems().stream().filter((e) -> !(e.getItemName().contains("押金")
//                || e.getItemName().contains("风险金")
//                || e.getItemName().contains("预备金")
//                || e.getItemName().contains("风险预备金")))
//                .collect(Collectors.toList()));
//        List<DepositRecordDO> depositRecordDOS = depositRecordMapper.selectList(new LambdaQueryWrapperX<DepositRecordDO>()
//                .eq(DepositRecordDO::getElderId, elderId)
//                .eq(DepositRecordDO::getTenantId, TenantContextHolder.getTenantId()));
//        List<ExpenseItemDO> depositList = depositRecordDOS.stream().map((e) -> new ExpenseItemDO().setItemId(e.getItemId())
//                .setItemName(e.getName())
//                .setAmount(e.getAmount())
//                .setActualAmount(e.getAmount())
//                .setTotalAmount(e.getAmount())
//                .setIsDeposit(BooleanEnum.TRUE.getValue())
//                .setIsMonthlyExpense(BooleanEnum.FALSE.getValue())
//                .setCount(1)).collect(Collectors.toList());
//        resVO.getExpenseItems().addAll(depositList);
//        //变更列表
//        List<ElderlyChangeRecordDO> elderlyChangeRecords = elderlyChangeRecordMapper.selectList(new LambdaQueryWrapperX<ElderlyChangeRecordDO>()
//                .eq(ElderlyChangeRecordDO::getElderlyId, elderId)
//                .eq(ElderlyChangeRecordDO::getCurrentFlag, 0));
//        resVO.setChangeRecords(elderlyChangeRecords);
//
//        return resVO;
//    }

    @Override
    public ElderlyContractResVO getContractByElderId(Long elderId) {
        ElderlyContractResVO resVO = new ElderlyContractResVO();

        ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(elderId);
        resVO.setElderName(elderlyInfo.getElderName());
        resVO.setElderTags(elderlyInfo.getElderTags());
        resVO.setBedName(buildService.getFullBedName(elderId));
        resVO.setCheckInTime(elderlyInfo.getCheckInTime());
        resVO.setNursingLevelName(elderlyInfo.getNurseLevelName());
        resVO.setSpecialCareNotes(elderlyInfo.getSpecialCareNotes());

        // 查询所有合同并按开始时间倒序排序
        List<ElderlyContractDO> elderlyContractList = elderlyContractMapper.selectList(new LambdaQueryWrapperX<ElderlyContractDO>()
                .eq(ElderlyContractDO::getElderId, elderlyInfo.getId())
                .orderByDesc(ElderlyContractDO::getBeginTime));

        // 根据当前时间确定每个合同的状态
        Date currentDate = new Date();

        if (CollectionUtil.isNotEmpty(elderlyContractList)) {
            for (ElderlyContractDO contract : elderlyContractList) {
                // 判断合同状态
                if (contract.getBeginTime().after(currentDate)) {
                    // 合同未开始
                    contract.setStatus(2);
                } else if (contract.getExpireTime().before(currentDate)) {
                    // 合同已过期
                    contract.setStatus(0);
                } else {
                    // 合同正在进行中
                    contract.setStatus(1);
                }
            }
        }

        resVO.setContracts(elderlyContractList);

        // 根据当前时间确定当前有效的合同
        ElderlyContractDO currentEffectiveContract = null;

        if (CollectionUtil.isNotEmpty(elderlyContractList)) {
            // 按照优先级查找当前有效的合同:
            // 1. 正在进行中的合同 (状态1)
            // 2. 最近的未开始合同 (状态2)
            // 3. 最新的已过期合同 (状态0)

            // 查找正在进行中的合同
            for (ElderlyContractDO contract : elderlyContractList) {
                if (contract.getStatus() == 1) {
                    currentEffectiveContract = contract;
                    break;
                }
            }

            // 如果没有正在进行中的合同，查找最近的未开始合同
            if (currentEffectiveContract == null) {
                for (ElderlyContractDO contract : elderlyContractList) {
                    if (contract.getStatus() == 2) {
                        currentEffectiveContract = contract;
                        break;
                    }
                }
            }

            // 如果仍然没有有效合同，使用最新的已过期合同
            if (currentEffectiveContract == null) {
                for (ElderlyContractDO contract : elderlyContractList) {
                    if (contract.getStatus() == 0) {
                        currentEffectiveContract = contract;
                        break;
                    }
                }
            }
        }

        // 根据当前有效的合同设置费用项
        // 查找与当前有效合同时间匹配的费用数据
        if (currentEffectiveContract != null) {
            // 查询在当前有效合同时间范围内的费用数据
            List<ExpenseDO> expenseList = expenseMapper.selectList(new LambdaQueryWrapperX<ExpenseDO>()
                    .eq(ExpenseDO::getElderId, elderlyInfo.getId())
                    .le(ExpenseDO::getCreatedTime, currentEffectiveContract.getExpireTime())
                    .ge(ExpenseDO::getCreatedTime, currentEffectiveContract.getBeginTime())
                    .orderByDesc(ExpenseDO::getCreatedTime));

            ExpenseDO expenseDO = null;
            if (CollectionUtil.isNotEmpty(expenseList)) {
                // 优先选择在合同时间范围内的费用数据
                expenseDO = expenseList.get(0);
            } else {
                // 如果没有在时间范围内的费用数据，则使用最新的费用数据
                Optional<ExpenseDO> optional = expenseMapper.selectList(new LambdaQueryWrapperX<ExpenseDO>()
                                .eq(ExpenseDO::getElderId, elderlyInfo.getId())
                                .orderByDesc(ExpenseDO::getCreatedTime))
                        .stream()
                        .findFirst();
                if (optional.isPresent()) {
                    expenseDO = optional.get();
                }
            }

            if (expenseDO != null) {
                List<ExpenseItemDO> expenseItems = expenseItemMapper.selectList(new LambdaQueryWrapperX<ExpenseItemDO>()
                        .eq(ExpenseItemDO::getExpenseId, expenseDO.getId()));
                BigDecimal sum = expenseItems.stream()
                        .map(ExpenseItemDO::getActualAmount)
                        .filter(Objects::nonNull)  // 过滤掉null值
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                resVO.setAmount(sum);
                resVO.setExpenseItems(expenseItems);
            }
        }

        if (resVO.getExpenseItems() != null) {
            resVO.setExpenseItems(resVO.getExpenseItems().stream().filter((e) -> !(e.getItemName().contains("押金")
                            || e.getItemName().contains("风险金")
                            || e.getItemName().contains("保证金")
                            || e.getItemName().contains("预备金")
                            || e.getItemName().contains("备用金")
                            || e.getItemName().contains("风险预备金")))
                    .collect(Collectors.toList()));
        }

        List<DepositRecordDO> depositRecordDOS = depositRecordMapper.selectList(new LambdaQueryWrapperX<DepositRecordDO>()
                .eq(DepositRecordDO::getElderId, elderId)
                .eq(DepositRecordDO::getTenantId, TenantContextHolder.getTenantId()));
        List<ExpenseItemDO> depositList = depositRecordDOS.stream().map((e) -> new ExpenseItemDO().setItemId(e.getItemId())
                .setItemName(e.getItemName())
                .setAmount(e.getAmount())
                .setActualAmount(e.getAmount())
                .setTotalAmount(e.getAmount())
                .setIsDeposit(BooleanEnum.TRUE.getValue())
                .setIsMonthlyExpense(BooleanEnum.FALSE.getValue())
                .setCount(1)).collect(Collectors.toList());

        if (resVO.getExpenseItems() != null) {
            resVO.getExpenseItems().addAll(depositList);
        } else {
            resVO.setExpenseItems(depositList);
        }

        //变更列表
        List<ElderlyChangeRecordDO> elderlyChangeRecords = elderlyChangeRecordMapper.selectList(new LambdaQueryWrapperX<ElderlyChangeRecordDO>()
                .eq(ElderlyChangeRecordDO::getElderlyId, elderId)
                .eq(ElderlyChangeRecordDO::getCurrentFlag, 0));
        for (ElderlyChangeRecordDO elderlyChangeRecord : elderlyChangeRecords) {
            if(elderlyChangeRecord.getOriginalAmount() == null){
                PriceChangeRecordDO priceChangeRecordDO = priceChangeRecordMapper.selectOne(PriceChangeRecordDO::getChangeId, elderlyChangeRecord.getId());
                elderlyChangeRecord.setOriginalAmount(priceChangeRecordDO.getOriginalAmount());
                elderlyChangeRecord.setAmount(priceChangeRecordDO.getAmount());
                elderlyChangeRecord.setActualAmount(priceChangeRecordDO.getAmount());
                // 因为是价格变更所以名称都使用原来的
                elderlyChangeRecord.setOverheadChargeId(priceChangeRecordDO.getOriginalId());
                elderlyChangeRecord.setOriginalName(priceChangeRecordDO.getOriginalName());
                elderlyChangeRecord.setExpectOverheadChargeId(priceChangeRecordDO.getOriginalId());
                elderlyChangeRecord.setExpectName(priceChangeRecordDO.getOriginalName());
            }
        }

        resVO.setChangeRecords(elderlyChangeRecords);

        return resVO;
    }

    @Override
    public void saveContractDetails(ElderlyContractDO contractDO) {
        Long id = contractDO.getId();
        ElderlyContractDO elderlyContractDO = elderlyContractMapper.selectById(id);
        List<ElderlyContractDetailDO> details = contractDO.getDetails();
        for (ElderlyContractDetailDO detail : details) {
            detail.setContractId(contractDO.getId());
            detail.setCreateDate(LocalDateTime.now());
            detail.setTenantId(elderlyContractDO.getTenantId());
            elderlyContractDetailMapper.insert(detail);
        }
    }

    @Override
    public void updateContract(ElderlyContractDO updateReqVO) {
        elderlyContractMapper.updateById(updateReqVO);
    }

    @Override
    public List<ElderlyContractDO> getExpiringWithinOneMonthContracts() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.MILLISECOND, 0);
        Date startDate = calendar.getTime();

        calendar.add(Calendar.MONTH, 1);
        calendar.set(Calendar.MILLISECOND, 0);
        Date endDate = calendar.getTime();

        List<ElderlyContractDO> contracts = elderlyContractMapper.selectExpiringWithinOneMonth(
                TenantContextHolder.getTenantId(), startDate, endDate);

        for (ElderlyContractDO contract : contracts) {
            TenantDO tenant = tenantService.getTenant(contract.getTenantId());
            contract.setTenantName(tenant == null ? null : tenant.getName());
            contract.setStatus(1);
        }
        return contracts;
    }
}
