package com.fs.his.service.impl;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.fs.common.core.redis.RedisCache;
import com.fs.common.exception.CustomException;
import com.fs.common.utils.DateUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fs.his.domain.FsStoreOrder;
import com.fs.his.dto.FsDoctorTaskDTO;
import com.fs.his.dto.SopDoctorTaskDto;
import com.fs.his.mapper.FsStoreOrderMapper;
import com.fs.his.service.IFsSopDoctorTaskService;
import com.fs.his.vo.SopDoctorTaskVo;
import com.fs.qw.domain.FsDoctorMemberSales;
import com.fs.qw.mapper.FsDoctorMemberSalesMapper;
import com.fs.sop.domain.SopOrderLog;
import com.fs.sop.mapper.SopOrderLogMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.fs.his.mapper.FsSopDoctorTaskMapper;
import com.fs.his.domain.FsSopDoctorTask;
import org.springframework.transaction.annotation.Transactional;

import static com.fs.his.utils.PhoneUtil.decryptPhone;

/**
 * 医生处理sop任务Service业务层处理
 * 
 * @author fs
 * @date 2025-12-25
 */
@Slf4j
@Service
public class FsSopDoctorTaskServiceImpl extends ServiceImpl<FsSopDoctorTaskMapper, FsSopDoctorTask> implements IFsSopDoctorTaskService {

    @Autowired
    private FsSopDoctorTaskMapper fsSopDoctorTaskMapper;

    @Autowired
    private SopOrderLogMapper sopOrderLogMapper;

    @Autowired
    private FsDoctorMemberSalesMapper doctorMemberSalesMapper;

    @Autowired
    private FsStoreOrderMapper fsStoreOrderMapper;

    @Autowired
    private RedisCache redisCache;
    /**
     * 查询医生处理sop任务
     * 
     * @param id 医生处理sop任务主键
     * @return 医生处理sop任务
     */
    @Override
    public SopDoctorTaskVo selectFsSopDoctorTaskVoById(Long id)
    {
        SopDoctorTaskVo sopDoctorTaskVo = fsSopDoctorTaskMapper.selectFsSopDoctorTaskVoById(id);
        //医生端查看客户手机号直接解密
        if (sopDoctorTaskVo!=null&&sopDoctorTaskVo.getPhone()!=null&&sopDoctorTaskVo.getPhone().length()>11){
            sopDoctorTaskVo.setPhone(decryptPhone(sopDoctorTaskVo.getPhone()));
        }
        return sopDoctorTaskVo;
    }

    /**
     * 查询医生处理sop任务列表
     * 
     * @param queryDto 医生处理sop任务
     * @return 医生处理sop任务
     */
    @Override
    public List<SopDoctorTaskVo> selectFsSopDoctorTaskVoList(SopDoctorTaskDto queryDto)
    {
        // 强制限定创建时间为今天
        String todayStart = new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(new Date());
        String todayEnd = new SimpleDateFormat("yyyy-MM-dd 23:59:59").format(new Date());
        queryDto.setBeginTime(todayStart);
        queryDto.setEndTime(todayEnd);
        return fsSopDoctorTaskMapper.selectFsSopDoctorTaskVoList(queryDto);
    }

    /**
     * 新增医生处理sop任务
     * 
     * @param fsSopDoctorTask 医生处理sop任务
     * @return 结果
     */
    @Override
    public int insertFsSopDoctorTask(FsSopDoctorTask fsSopDoctorTask)
    {
        fsSopDoctorTask.setCreateTime(DateUtils.getNowDate());
        return fsSopDoctorTaskMapper.insertFsSopDoctorTask(fsSopDoctorTask);
    }

    /**
     * 修改医生处理sop任务
     * 
     * @param fsSopDoctorTask 医生处理sop任务
     * @return 结果
     */
    @Override
    public int updateFsSopDoctorTask(FsSopDoctorTask fsSopDoctorTask)
    {
        fsSopDoctorTask.setUpdateTime(DateUtils.getNowDate());
        return fsSopDoctorTaskMapper.updateFsSopDoctorTask(fsSopDoctorTask);
    }

    /**
     * 批量删除医生处理sop任务
     * 
     * @param ids 需要删除的医生处理sop任务主键
     * @return 结果
     */
    @Override
    public int deleteFsSopDoctorTaskByIds(Long[] ids)
    {
        return fsSopDoctorTaskMapper.deleteFsSopDoctorTaskByIds(ids);
    }

    /**
     * 删除医生处理sop任务信息
     * 
     * @param id 医生处理sop任务主键
     * @return 结果
     */
    @Override
    public int deleteFsSopDoctorTaskById(Long id)
    {
        return fsSopDoctorTaskMapper.deleteFsSopDoctorTaskById(id);
    }

    @Override
    public List<SopDoctorTaskVo> statsDoctorOverviewAllList(SopDoctorTaskDto queryDto) {
        return fsSopDoctorTaskMapper.selectFsSopDoctorTaskVoList(queryDto);
    }

    @Override
    public List<FsSopDoctorTask> selectFsSopDoctorTaskList(FsSopDoctorTask param) {
        param.setHandlePersonType(1); // 医生所属任务
        // 医生只能看到自己的初始任务(1)和提醒任务(2)
        param.setTaskType(1); // 先查初始任务
        param.setStatus(0);
        List<FsSopDoctorTask> result = new ArrayList<>();
        List<FsSopDoctorTask> initialTasks = fsSopDoctorTaskMapper.selectFsSopDoctorTaskList(param);
        result.addAll(initialTasks);

        // 再查提醒任务
        param.setTaskType(3);
        List<FsSopDoctorTask> reminderTasks = fsSopDoctorTaskMapper.selectFsSopDoctorTaskList(param);
        result.addAll(reminderTasks);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int submitDoctorTask(FsDoctorTaskDTO addTaskDto) {
        // --- 1. 验证输入参数 ---
        if (addTaskDto == null || addTaskDto.getId() == null) {
            throw new CustomException("任务ID不能为空");
        }
        if (addTaskDto.getDoctorMemberSalesId() == null) {
            throw new CustomException("医生会员搭销ID不能为空");
        }
        // 对于签收类型，检查订单号是否提供
        if (addTaskDto.getHandleType() != null && addTaskDto.getHandleType() == 1
                && (addTaskDto.getOrderCode() == null || addTaskDto.getOrderCode().isEmpty())) {
            throw new CustomException("签收类型必须提供订单号");
        }
        // 对于提醒类型，检查天数是否提供且有效
        if (addTaskDto.getHandleType() != null && addTaskDto.getHandleType() == 2
                && (addTaskDto.getSendDays() == null || addTaskDto.getSendDays() <= 0)) {
            throw new CustomException("提醒类型必须提供大于0的天数");
        }
        // 获取会员搭销数据
        FsDoctorMemberSales fsDoctorMemberSales = doctorMemberSalesMapper.selectFsDoctorMemberSalesById(addTaskDto.getDoctorMemberSalesId());
        if (fsDoctorMemberSales == null) {
            log.error("会员搭销数据不存在,doctorMemberSalesId:{}", addTaskDto.getDoctorMemberSalesId());
            throw new CustomException("会员搭销ID不存在");
        }
        FsSopDoctorTask existingTask = fsSopDoctorTaskMapper.selectFsSopDoctorTaskById(addTaskDto.getId());
        if (existingTask == null) {
            throw new CustomException("任务不存在，无法处理");
        }
        if (existingTask.getStatus() != null && existingTask.getStatus() == 1) {
            // 如果任务已经是已处理状态，直接抛出异常
            throw new CustomException("该任务已被处理，请返回跟'进会员面页'面后重试");
        }
        // 检查任务类型，必须是初始任务才能处理
        if (existingTask.getTaskType() != null && existingTask.getTaskType() != 1) {
            throw new CustomException("非初始任务不能处理");
        }
        Integer currentVersion = existingTask.getVersion();
        // --- 2. 签收任务处理：需要找到另一个人的初始任务并标记为已处理 ---
        if (addTaskDto.getHandleType() == 1) {
            // 查找另一个人的初始任务（医生找销售的，销售找医生的）
            FsSopDoctorTask otherPersonTask = findOtherPersonTask(
                    existingTask.getDoctorMemberSalesId(),
                    existingTask.getHandlePersonType(),
                    existingTask.getCompanyUserId(),
                    existingTask.getDoctorId()
            );

            if (otherPersonTask != null && otherPersonTask.getStatus() == 0) {
                // 标记另一个人的初始任务为已处理
                FsSopDoctorTask updateOther = new FsSopDoctorTask();
                updateOther.setId(otherPersonTask.getId());
                updateOther.setStatus(1);
                updateOther.setUpdateTime(DateUtils.getNowDate());
                updateOther.setRemark("此任务已被其他人签收处理");
                updateOther.setVersion(otherPersonTask.getVersion());
                fsSopDoctorTaskMapper.updateFsSopDoctorTask(updateOther);
            }
        }
        // --- 3. 更新当前任务 ---
        FsSopDoctorTask doctorTask = new FsSopDoctorTask();
        doctorTask.setId(addTaskDto.getId());
        doctorTask.setVersion(currentVersion); //设置旧版本号，用于乐观锁 WHERE 条件
        doctorTask.setDoctorId(addTaskDto.getDoctorId());
        doctorTask.setStatus(1); // 0:待处理，1:已处理
        doctorTask.setUserId(fsDoctorMemberSales.getFsUserId()); // 会员id
        doctorTask.setHandleType(addTaskDto.getHandleType());
        doctorTask.setRemark(addTaskDto.getRemark());
        doctorTask.setUpdateTime(DateUtils.getNowDate());
        doctorTask.setSendDays(addTaskDto.getSendDays());
        doctorTask.setHandlePersonType(existingTask.getHandlePersonType());// 保持原处理人类型
        // 设置任务类型
        if (addTaskDto.getHandleType() == 1) {
            doctorTask.setTaskType(2); // 签收任务
        } else if (addTaskDto.getHandleType() == 2) {
            doctorTask.setTaskType(3); // 提醒任务
        }
        //"签收"类型 额外处理
        if (addTaskDto.getHandleType() == 1) {
            doctorTask.setOrderCode(addTaskDto.getOrderCode());
            //缓存签收的doctorTask
            String signOffOrderCacheKey = "doctorMemberSaLes:"+ addTaskDto.getOrderCode();
            redisCache.setCacheObject(signOffOrderCacheKey,doctorTask);
            //修改fs_store_order表的is_receive_notice为已签收
            FsStoreOrder fsStoreOrder=new FsStoreOrder();
            fsStoreOrder.setIsReceiveNotice(1);//已签收
            fsStoreOrder.setOrderCode(addTaskDto.getOrderCode());
            fsStoreOrderMapper.updateFsStoreOrderByOrderCode(fsStoreOrder);
        }
        // 更新当前任务
        int updateResult = fsSopDoctorTaskMapper.updateFsSopDoctorTask(doctorTask);
        if (updateResult == 0) {
            // 更新影响行数为0，说明乐观锁生效，数据已被其他线程修改
            log.warn("提交任务时发生冲突，任务ID: {}, 原始版本号: {}", addTaskDto.getId(), currentVersion);
            throw new CustomException("该任务已被他人处理，请刷新后重试");
        }
        // --- 4. 提醒任务：创建定时提醒日志 ---
        if (addTaskDto.getHandleType() == 2) {
            // --- 4.1 计算提醒时间 ---
            Date now = DateUtils.getNowDate();
            Date futureDate = calculateFutureDate(now, addTaskDto.getSendDays());

            // --- 4.2 插入sop_order_log表 ---
            SopOrderLog sopOrderLog = new SopOrderLog();
            sopOrderLog.setDoctorId(addTaskDto.getDoctorId());// 医生ID
            sopOrderLog.setStatus(0); // 0:未发送，1:已发送
            sopOrderLog.setFsUserId(fsDoctorMemberSales.getFsUserId());
            sopOrderLog.setCompanyUserId(addTaskDto.getCompanyUserId());
            sopOrderLog.setRemark(addTaskDto.getRemark());
            sopOrderLog.setExId(addTaskDto.getExId());
            sopOrderLog.setCreateTime(now);
            sopOrderLog.setSendTime(futureDate);
            sopOrderLog.setDoctorMemberSalesId(addTaskDto.getDoctorMemberSalesId());
            sopOrderLog.setHandlePersonType(existingTask.getHandlePersonType()); // 记录处理人类型
            sopOrderLogMapper.insertSopOrderLog(sopOrderLog);
        }

        return updateResult;
    }

    /**
     * 查询跟进会员任务处理记录
     * */
    @Override
    public List<SopDoctorTaskVo> selectSopDoctorTaskVoProcessRecordList(SopDoctorTaskDto queryDto) {
        // ---验证输入参数 ---
        //if (queryDto == null || queryDto.getDoctorMemberSalesId() == null) {
            //throw new CustomException("医生会员搭销ID不能为空");
        //}
        queryDto.setStatus(1);//1:已处理
        return fsSopDoctorTaskMapper.selectSopDoctorTaskVoProcessRecordList(queryDto);
    }

    /**
     * 销售查询任务列表
     */
    public List<FsSopDoctorTask> getSalesTaskList(FsSopDoctorTask param) {
        param.setHandlePersonType(2); // 销售人员所属任务
        // 销售只能看到自己的初始任务(1)和提醒任务(3)
        param.setTaskType(1); // 先查初始任务
        param.setStatus(0);
        List<FsSopDoctorTask> result = new ArrayList<>();
        List<FsSopDoctorTask> initialTasks = fsSopDoctorTaskMapper.selectFsSopDoctorTaskList(param);
        result.addAll(initialTasks);

        // 再查提醒任务
        param.setTaskType(3);
        List<FsSopDoctorTask> reminderTasks = fsSopDoctorTaskMapper.selectFsSopDoctorTaskList(param);
        result.addAll(reminderTasks);

        return result;
    }

    /**
     * 销售查询签收任务（已处理的）
     */
    public List<FsSopDoctorTask> getSalesSignOffTasks(FsSopDoctorTask param) {
        param.setHandlePersonType(2); // 销售人员的任务
        param.setTaskType(2); // 签收任务
        param.setStatus(1);   // 已处理

        return fsSopDoctorTaskMapper.selectFsSopDoctorTaskList(param);
    }

    /**
     * 查找另一个人的初始任务
     */
    private FsSopDoctorTask findOtherPersonTask(Long memberSalesId, Integer currentHandlePersonType,
                                                Long companyUserId, Long doctorId) {

        FsSopDoctorTask query = new FsSopDoctorTask();
        query.setDoctorMemberSalesId(memberSalesId);
        query.setTaskType(1); // 只查找初始任务
        query.setStatus(0);   // 只查找未处理的任务

        if (currentHandlePersonType == 1) { // 当前是医生，找销售的
            query.setHandlePersonType(2); // 销售的任务
            query.setCompanyUserId(companyUserId);
        } else { // 当前是销售，找医生的
            query.setHandlePersonType(1); // 医生的任务
            query.setDoctorId(doctorId);
        }

        List<FsSopDoctorTask> tasks = fsSopDoctorTaskMapper.selectFsSopDoctorTaskList(query);
        return tasks != null && !tasks.isEmpty() ? tasks.get(0) : null;
    }
    /**
     * 计算未来日期
     * @param baseDate 基准日期
     * @param daysToAdd 需要增加的天数
     * @return 计算后的未来日期（时间为 00:00:00）
     */
    public Date calculateFutureDate(Date baseDate, Integer daysToAdd) {
        if (baseDate == null || daysToAdd == null || daysToAdd <= 0) {
            throw new CustomException("基准日期和增加天数都不能为空且天数需大于0");
        }

        // 1. 将 Date 转换为 Instant，再转换为 LocalDate (忽略时区影响，只取日期部分)
        LocalDate localDate = baseDate.toInstant()
                .atZone(ZoneId.systemDefault()) // 使用系统默认时区进行转换
                .toLocalDate();                 // toLocalDate() 自动丢弃时间信息

        // 2. 使用 plusDays 添加天数，得到目标日期
        LocalDate targetDate = localDate.plusDays(daysToAdd);

        // 3. 将 LocalDate 转换为当天的开始时刻 (00:00:00) 的 LocalDateTime
        LocalDateTime startOfDay = targetDate.atStartOfDay(); //生成 YYYY-MM-DDT00:00:00

        // 4. 将 LocalDateTime 转换回 Date
        return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
    }
}
