package org.dromara.web.service.impl;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.*;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.mapper.SysDeptMapper;
import org.dromara.system.mapper.SysUserMapper;
import org.dromara.web.domain.EnteralNutrition;
import org.dromara.web.domain.Settlement;
import org.dromara.web.domain.TreatmentUser;
import org.dromara.web.domain.bo.LongTermManagementExecuteBo;
import org.dromara.web.domain.bo.LongTermManagementListPageBo;
import org.dromara.web.domain.bo.LongTermManagementStopBo;
import org.dromara.web.domain.vo.LongTermManagementListPageVo;
import org.dromara.web.mapper.EnteralNutritionMapper;
import org.dromara.web.mapper.SettlementMapper;
import org.dromara.web.mapper.TreatmentUserMapper;
import org.dromara.web.service.LongTermManagementService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @Author: Huanyi
 * @CreateTime: 2025-08-25
 * @Description:
 * @Version: 1.0
 */

@Service
@RequiredArgsConstructor
@Slf4j
public class LongTermManagementServiceImpl implements LongTermManagementService {

    private final EnteralNutritionMapper enteralNutritionMapper;
    private final SettlementMapper settlementMapper;
    private final TreatmentUserMapper treatmentUserMapper;
    private final SysDeptMapper sysDeptMapper;
    private final SysUserMapper sysUserMapper;

    @Override
    public TableDataInfo listPage(LongTermManagementListPageBo bo, PageQuery pageQuery) {

        List<Long> patientIds = new ArrayList<>();
        Map<Long, String> patientNames = new HashMap<>();
        List<TreatmentUser> patientList = treatmentUserMapper.selectList(
            Wrappers.lambdaQuery(TreatmentUser.class)
                .like(bo.getPatientName() != null, TreatmentUser::getTreatName, bo.getPatientName())
                .eq(bo.getConsultationType() != null, TreatmentUser::getType, bo.getConsultationType())
                .eq(bo.getWardId() != null, TreatmentUser::getWardId, bo.getWardId())
        );
        patientList.forEach(e -> {
            patientIds.add(e.getId());
            patientNames.put(e.getId(), e.getTreatName());
        });

        Map<Long, String> deptMap = new HashMap<>();
        sysDeptMapper.selectList().forEach(e -> deptMap.put(e.getDeptId(), e.getDeptName()));
        Map<Long, String> doctorMap = new HashMap<>();
        sysUserMapper.selectList().forEach(e -> doctorMap.put(e.getUserId(), e.getName()));

        Page<EnteralNutrition> page = enteralNutritionMapper.selectPage(
            pageQuery.build(),
            Wrappers.lambdaQuery(EnteralNutrition.class)
                .ge(bo.getCreateTimeEarliest() != null, EnteralNutrition::getCreateTime, bo.getCreateTimeEarliest())
                .le(bo.getCreateTimeLatest() != null, EnteralNutrition::getCreateTime, bo.getCreateTimeLatest())
                .ge(bo.getExecuteTimeEarliest() != null, EnteralNutrition::getExecuteTime, bo.getExecuteTimeEarliest())
                .le(bo.getExecuteTimeLatest() != null, EnteralNutrition::getExecuteTime, bo.getExecuteTimeLatest())
                .eq(bo.getExecuteStatus() != null, EnteralNutrition::getExecuteStatus, bo.getExecuteStatus())
                .eq(EnteralNutrition::getStatus, "0")
                .eq(EnteralNutrition::getExecuteStatus, "0")
        );

        List<Long> settlementIds = new ArrayList<>();
        page.getRecords().forEach(e -> settlementIds.add(e.getSettlementId()));

        List<Settlement> settlementList = settlementMapper.selectList(
            Wrappers.lambdaQuery(Settlement.class).in(!settlementIds.isEmpty(), Settlement::getId, settlementIds)
        );

        return TableDataInfo.build(page.convert(e -> {
            LongTermManagementListPageVo vo = new LongTermManagementListPageVo();
            vo.setId(e.getId());
            vo.setExecuteTime(e.getExecuteTime());
            vo.setCreateTime(e.getCreateTime());
            vo.setMealTime(e.getMealTime());
            vo.setExecuteStatus(Objects.equals(e.getExecuteStatus(), "0") ? "未执行" : "已执行");
            vo.setStopTime(e.getStopDate());
            vo.setSettlementId(e.getSettlementId());
            vo.setNutritionDetail(e.getNutritionProduct());
            vo.setPatientDepartment(deptMap.get(e.getCreateDept()));

            for (Settlement settlement : settlementList) {
                if (Objects.equals(settlement.getId(), e.getSettlementId())) {
                    vo.setPatientId(settlement.getPatientId());
                    vo.setPatientName(patientNames.get(settlement.getPatientId()));
                    vo.setConsultationType(Objects.equals(settlement.getVisitType(), "0") ? "门诊" : "住院");
                    vo.setMedicalId(settlement.getPatientNo());
                    vo.setWardName(settlement.getWardName());
                    vo.setBedId(settlement.getBedNo());
                }
            }

            vo.setDoctorName(doctorMap.get(e.getCreateBy()));
            vo.setDoctorDepartment(deptMap.get(e.getCreateDept()));
            vo.setNote(e.getPrescriptionRemark());
            return vo;
        }));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R execute(LongTermManagementExecuteBo bo) {

        LoginUser loginUser = LoginHelper.getLoginUser();

        int flag = enteralNutritionMapper.update(
            Wrappers.lambdaUpdate(EnteralNutrition.class).eq(EnteralNutrition::getId, bo.getId())
                .set(EnteralNutrition::getExecuteStatus, "1")
                .set(EnteralNutrition::getExecuteBy, Objects.nonNull(loginUser) ? loginUser.getUserId() : null)
                .set(EnteralNutrition::getExecuteTime, LocalTime.now())
                .set(EnteralNutrition::getExecuteDate, LocalDate.now())
        );
        if (flag <= 0) throw new RuntimeException("执行失败");

        return R.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R stop(LongTermManagementStopBo bo) {

        EnteralNutrition nutrition = enteralNutritionMapper.selectOne(
            Wrappers.lambdaQuery(EnteralNutrition.class).eq(EnteralNutrition::getId, bo.getId())
        );

        if (Objects.isNull(nutrition)) throw new RuntimeException("找不到该处方");

        int settlementFlag = settlementMapper.update(
            Wrappers.lambdaUpdate(Settlement.class).eq(Settlement::getId, nutrition.getSettlementId())
                .set(Settlement::getStatus, "1").set(Settlement::getStopDate, new Date())
        );
        if (settlementFlag <= 0) throw new RuntimeException("停嘱失败");

        int enteralNutritionFlag = enteralNutritionMapper.update(
            Wrappers.lambdaUpdate(EnteralNutrition.class).eq(EnteralNutrition::getSettlementId, nutrition.getSettlementId())
                .set(EnteralNutrition::getStatus, "1").set(EnteralNutrition::getStopDate, new Date())
        );
        if (enteralNutritionFlag <= 0) throw new RuntimeException("批量停嘱失败");

        return R.ok();
    }
}
