package com.ruoyi.web.modules.diagnosis.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.modules.diagnosis.domain.BizConsultMessage;
import com.ruoyi.web.modules.diagnosis.domain.BizConsultSession;
import com.ruoyi.web.modules.diagnosis.domain.BizMedicalResource;
import com.ruoyi.web.modules.diagnosis.domain.ConsultPushPayload;
import com.ruoyi.web.modules.diagnosis.domain.VetConsultSendBody;
import com.ruoyi.web.modules.diagnosis.mapper.BizConsultMessageMapper;
import com.ruoyi.web.modules.diagnosis.mapper.BizConsultSessionMapper;
import com.ruoyi.web.modules.diagnosis.mapper.BizMedicalResourceMapper;
import com.ruoyi.web.modules.diagnosis.service.IBizVetOnlineConsultService;
import com.ruoyi.web.modules.diagnosis.support.ConsultMessagePreview;
import com.ruoyi.web.modules.diagnosis.support.ConsultPushService;
import com.ruoyi.web.modules.diagnosis.support.ConsultSessionRules;
import com.ruoyi.web.modules.diagnosis.support.ConsultThreeMonthsWindow;
import com.ruoyi.web.modules.diagnosis.support.OnlineConsultVetSupport;
import com.ruoyi.web.modules.diagnosis.support.VetConsultValidation;
import com.ruoyi.web.modules.diagnosis.support.VetProviderResolver;

/**
 * 在线接诊（兽医）服务实现。
 */
@Service
public class BizVetOnlineConsultServiceImpl implements IBizVetOnlineConsultService
{
    @Autowired
    private BizConsultSessionMapper bizConsultSessionMapper;

    @Autowired
    private BizConsultMessageMapper bizConsultMessageMapper;

    @Autowired
    private BizMedicalResourceMapper bizMedicalResourceMapper;

    @Autowired
    private VetProviderResolver vetProviderResolver;

    @Autowired
    private ConsultPushService consultPushService;

    @Autowired
    private ISysUserService sysUserService;

    @Override
    public List<BizConsultSession> selectVetSessionList(BizConsultSession query, Long sysUserId)
    {
        Long providerId = vetProviderResolver.resolveProviderId(sysUserId);
        if (providerId == null)
        {
            return new ArrayList<>();
        }
        BizConsultSession criteria = buildListCriteria(query, providerId);
        VetConsultValidation.validateListQuery(criteria, criteria.getSearchMode());
        List<BizConsultSession> list = bizConsultSessionMapper.selectVetSessionList(criteria);
        return list != null ? list : new ArrayList<>();
    }

    @Override
    public List<BizConsultMessage> selectSessionMessages(Long sessionId, Long beforeId, Integer pageSize, Long sysUserId)
    {
        BizConsultSession session = loadVetOwnedSession(sessionId, sysUserId, false);
        int size = pageSize != null && pageSize > 0 ? pageSize : ConsultSessionRules.DEFAULT_MESSAGE_PAGE_SIZE;
        List<BizConsultMessage> batch = bizConsultMessageMapper.selectMessagesBeforeId(session.getId(), beforeId, size);
        if (batch == null || batch.isEmpty())
        {
            return new ArrayList<>();
        }
        List<BizConsultMessage> asc = new ArrayList<>(batch);
        Collections.reverse(asc);
        return asc;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BizConsultMessage sendVetMessage(Long sessionId, VetConsultSendBody body, Long sysUserId, String senderName)
    {
        BizConsultSession session = loadVetOwnedSession(sessionId, sysUserId, true);
        VetConsultValidation.validateSendBody(body);
        return persistAndPush(session, body, ConsultSessionRules.SENDER_ROLE_RECEIVER, sysUserId, senderName);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BizConsultSession openOrGetVetSession(Long vetResourceId, Long askerUserId, String askerName)
    {
        if (vetResourceId == null)
        {
            throw new ServiceException("请选择兽医");
        }
        if (askerUserId == null)
        {
            throw new ServiceException("请先登录");
        }
        BizMedicalResource vet = bizMedicalResourceMapper.selectBizMedicalResourceById(vetResourceId);
        if (!OnlineConsultVetSupport.isConsultablePublishedVet(vet))
        {
            throw new ServiceException("该兽医暂不支持在线问诊");
        }
        BizConsultSession existing = bizConsultSessionMapper.selectVetSessionByAskerAndProvider(askerUserId,
                vetResourceId);
        if (existing != null)
        {
            return existing;
        }
        String resolvedAskerName = resolveDisplayName(askerUserId, askerName);
        Date now = new Date();
        BizConsultSession row = new BizConsultSession();
        row.setConsultType(ConsultSessionRules.CONSULT_TYPE_VET);
        row.setAskerUserId(askerUserId);
        row.setAskerName(resolvedAskerName);
        row.setReceiverUserId(vet.getSysUserId());
        row.setReceiverProviderId(vet.getId());
        row.setReceiverName(vet.getResourceName());
        row.setVetVisible(ConsultSessionRules.VET_VISIBLE_YES);
        row.setCreateTime(now);
        row.setUpdateTime(now);
        bizConsultSessionMapper.insertBizConsultSession(row);
        return row;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BizConsultMessage sendAskerMessage(Long sessionId, VetConsultSendBody body, Long askerUserId, String askerName)
    {
        if (askerUserId == null)
        {
            throw new ServiceException("请先登录");
        }
        BizConsultSession session = bizConsultSessionMapper.selectSessionByIdAndAsker(sessionId, askerUserId);
        if (session == null || session.getVetVisible() == null
                || session.getVetVisible() != ConsultSessionRules.VET_VISIBLE_YES)
        {
            throw new ServiceException("会话不存在或已删除");
        }
        VetConsultValidation.validateSendBody(body);
        return persistAndPush(session, body, ConsultSessionRules.SENDER_ROLE_ASKER, askerUserId,
                resolveDisplayName(askerUserId, askerName));
    }

    @Override
    public List<BizConsultSession> selectAskerSessionList(BizConsultSession query)
    {
        if (query == null || query.getAskerUserId() == null)
        {
            return new ArrayList<>();
        }
        List<BizConsultSession> list = bizConsultSessionMapper.selectAskerSessionList(query);
        return list != null ? list : new ArrayList<>();
    }

    @Override
    public List<BizConsultMessage> selectAskerSessionMessages(Long sessionId, Long beforeId, Integer pageSize,
            Long askerUserId)
    {
        if (askerUserId == null)
        {
            throw new ServiceException("请先登录");
        }
        BizConsultSession session = bizConsultSessionMapper.selectSessionByIdAndAsker(sessionId, askerUserId);
        if (session == null || session.getVetVisible() == null
                || session.getVetVisible() != ConsultSessionRules.VET_VISIBLE_YES)
        {
            throw new ServiceException("会话不存在或已删除");
        }
        int size = pageSize != null && pageSize > 0 ? pageSize : ConsultSessionRules.DEFAULT_MESSAGE_PAGE_SIZE;
        List<BizConsultMessage> batch = bizConsultMessageMapper.selectMessagesBeforeId(session.getId(), beforeId, size);
        if (batch == null || batch.isEmpty())
        {
            return new ArrayList<>();
        }
        List<BizConsultMessage> asc = new ArrayList<>(batch);
        Collections.reverse(asc);
        return asc;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int hideSessionForVet(Long sessionId, Long askerUserId)
    {
        if (sessionId == null || askerUserId == null)
        {
            throw new ServiceException("会话不存在或已删除");
        }
        int rows = bizConsultSessionMapper.updateVetVisible(sessionId, askerUserId, ConsultSessionRules.VET_VISIBLE_NO);
        if (rows <= 0)
        {
            throw new ServiceException("会话不存在或已删除");
        }
        return rows;
    }

    private BizConsultMessage persistAndPush(BizConsultSession session, VetConsultSendBody body, int senderRole,
            Long senderUserId, String senderName)
    {
        Date now = new Date();
        String content = StringUtils.trim(body.getContent());
        BizConsultMessage message = new BizConsultMessage();
        message.setSessionId(session.getId());
        message.setSenderRole(senderRole);
        message.setSenderUserId(senderUserId);
        message.setSenderName(senderName);
        message.setMsgType(body.getMsgType());
        message.setContent(content);
        message.setMediaDuration(body.getMediaDuration());
        message.setSendTime(now);
        message.setCreateTime(now);
        bizConsultMessageMapper.insertBizConsultMessage(message);

        String preview = ConsultMessagePreview.build(body.getMsgType(), content);
        BizConsultSession patch = new BizConsultSession();
        patch.setId(session.getId());
        patch.setLastMessageTime(now);
        patch.setLastMessagePreview(preview);
        patch.setUpdateTime(now);
        if (body.getMsgType() == ConsultSessionRules.MSG_TYPE_TEXT && StringUtils.isEmpty(session.getSessionTitle()))
        {
            patch.setSessionTitle(preview);
        }
        bizConsultSessionMapper.updateSessionLastMessage(patch);

        ConsultPushPayload push = buildPushPayload(message, session, preview, now);
        consultPushService.publishNewMessage(push);
        return message;
    }

    private ConsultPushPayload buildPushPayload(BizConsultMessage message, BizConsultSession session, String preview,
            Date lastTime)
    {
        ConsultPushPayload payload = new ConsultPushPayload();
        payload.setMessageId(message.getId());
        payload.setSessionId(session.getId());
        payload.setSenderRole(message.getSenderRole());
        payload.setSenderName(message.getSenderName());
        payload.setMsgType(message.getMsgType());
        payload.setContent(message.getContent());
        payload.setMediaDuration(message.getMediaDuration());
        payload.setSendTime(message.getSendTime());
        payload.setLastMessagePreview(preview);
        payload.setLastMessageTime(lastTime);
        payload.setVetUserId(session.getReceiverUserId());
        payload.setAskerUserId(session.getAskerUserId());
        return payload;
    }

    private BizConsultSession buildListCriteria(BizConsultSession query, Long providerId)
    {
        BizConsultSession criteria = new BizConsultSession();
        criteria.setConsultType(ConsultSessionRules.CONSULT_TYPE_VET);
        criteria.setReceiverProviderId(providerId);
        criteria.setVetVisible(ConsultSessionRules.VET_VISIBLE_YES);
        if (query != null)
        {
            criteria.setSearchMode(query.getSearchMode());
            criteria.setAskerNameFilter(StringUtils.trim(query.getAskerName()));
            criteria.setContentKeyword(StringUtils.trim(query.getContentKeyword()));
        }
        if (!Boolean.TRUE.equals(criteria.getSearchMode()))
        {
            criteria.setThreeMonthsAgo(ConsultThreeMonthsWindow.calcThreeMonthsAgo(new Date()));
        }
        return criteria;
    }

    private BizConsultSession loadVetOwnedSession(Long sessionId, Long sysUserId, boolean forWrite)
    {
        if (sessionId == null)
        {
            throw new ServiceException("会话不存在或已删除");
        }
        Long providerId = vetProviderResolver.resolveProviderId(sysUserId);
        if (providerId == null)
        {
            if (forWrite)
            {
                throw new ServiceException("未绑定兽医资源，无法接诊");
            }
            throw new ServiceException("未绑定兽医资源，无法接诊");
        }
        BizConsultSession session = bizConsultSessionMapper.selectVetSessionByIdAndProvider(sessionId, providerId);
        if (session == null)
        {
            throw new ServiceException(forWrite ? "无权查看该会话" : "无权查看该会话");
        }
        return session;
    }

    private String resolveDisplayName(Long userId, String fallback)
    {
        if (StringUtils.isNotEmpty(fallback))
        {
            return fallback.trim();
        }
        try
        {
            com.ruoyi.common.core.domain.entity.SysUser user = sysUserService.selectUserById(userId);
            if (user != null && StringUtils.isNotEmpty(user.getNickName()))
            {
                return user.getNickName();
            }
            if (user != null && StringUtils.isNotEmpty(user.getUserName()))
            {
                return user.getUserName();
            }
        }
        catch (Exception ignored)
        {
            // 测试环境可能无用户表
        }
        return "用户" + userId;
    }
}
