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

import java.util.ArrayList;
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.web.modules.diagnosis.domain.BizServiceAppointment;
import com.ruoyi.web.modules.diagnosis.mapper.BizServiceAppointmentMapper;
import com.ruoyi.web.modules.diagnosis.service.IBizVetMyAppointmentService;
import com.ruoyi.web.modules.diagnosis.support.ServiceAppointmentRules;
import com.ruoyi.web.modules.diagnosis.support.VetAppointmentStatusResolver;
import com.ruoyi.web.modules.diagnosis.support.VetAppointmentValidation;
import com.ruoyi.web.modules.diagnosis.support.VetProviderResolver;

/**
 * 我的预约（兽医）服务实现。
 */
@Service
public class BizVetMyAppointmentServiceImpl implements IBizVetMyAppointmentService
{
    @Autowired
    private BizServiceAppointmentMapper bizServiceAppointmentMapper;

    @Autowired
    private VetProviderResolver vetProviderResolver;

    @Override
    public List<BizServiceAppointment> selectVetAppointmentList(BizServiceAppointment query, Long sysUserId)
    {
        Long providerId = vetProviderResolver.resolveProviderId(sysUserId);
        if (providerId == null)
        {
            return new ArrayList<>();
        }
        VetAppointmentValidation.validateListQuery(query);
        BizServiceAppointment criteria = query != null ? query : new BizServiceAppointment();
        criteria.setProviderType(ServiceAppointmentRules.PROVIDER_TYPE_VET);
        criteria.setProviderId(providerId);
        List<BizServiceAppointment> list = bizServiceAppointmentMapper.selectVetAppointmentList(criteria);
        if (list != null)
        {
            for (BizServiceAppointment row : list)
            {
                enrichRow(row);
            }
        }
        return list;
    }

    @Override
    public BizServiceAppointment selectVetAppointmentById(Long id, Long sysUserId)
    {
        BizServiceAppointment row = loadOwnedRow(id, sysUserId, false);
        enrichRow(row);
        return row;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int confirm(Long id, Long sysUserId, String operator)
    {
        BizServiceAppointment owned = loadOwnedRow(id, sysUserId, true);
        assertPendingForAction(owned, true);
        Date now = new Date();
        BizServiceAppointment patch = new BizServiceAppointment();
        patch.setId(id);
        patch.setProviderId(owned.getProviderId());
        patch.setConfirmTime(now);
        patch.setUpdateBy(operator);
        patch.setUpdateTime(now);
        int rows = bizServiceAppointmentMapper.updateConfirmVetAppointment(patch);
        if (rows <= 0)
        {
            throwStatusChanged(owned.getId(), owned.getProviderId(), true);
        }
        return rows;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int reject(Long id, String rejectReason, Long sysUserId, String operator)
    {
        String reason = VetAppointmentValidation.trimRejectReason(rejectReason);
        VetAppointmentValidation.validateRejectReason(reason);
        BizServiceAppointment owned = loadOwnedRow(id, sysUserId, true);
        assertPendingForAction(owned, false);
        Date now = new Date();
        BizServiceAppointment patch = new BizServiceAppointment();
        patch.setId(id);
        patch.setProviderId(owned.getProviderId());
        patch.setRejectReason(reason);
        patch.setRejectTime(now);
        patch.setUpdateBy(operator);
        patch.setUpdateTime(now);
        int rows = bizServiceAppointmentMapper.updateRejectVetAppointment(patch);
        if (rows <= 0)
        {
            throwStatusChanged(owned.getId(), owned.getProviderId(), false);
        }
        return rows;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int complete(Long id, Long sysUserId, String operator)
    {
        BizServiceAppointment owned = loadOwnedRow(id, sysUserId, true);
        assertCanComplete(owned);
        Date now = new Date();
        BizServiceAppointment patch = new BizServiceAppointment();
        patch.setId(id);
        patch.setProviderId(owned.getProviderId());
        patch.setUpdateBy(operator);
        patch.setUpdateTime(now);
        int rows = bizServiceAppointmentMapper.updateCompleteVetAppointment(patch);
        if (rows <= 0)
        {
            throwCompleteNotAllowed(owned.getId(), owned.getProviderId());
        }
        return rows;
    }

    private BizServiceAppointment loadOwnedRow(Long id, Long sysUserId, boolean forWrite)
    {
        if (id == null)
        {
            throw new ServiceException("预约记录不存在");
        }
        Long providerId = vetProviderResolver.resolveProviderId(sysUserId);
        if (providerId == null)
        {
            if (forWrite)
            {
                throw new ServiceException("未绑定兽医资源，无法操作");
            }
            throw new ServiceException("未绑定兽医资源，无法查询预约");
        }
        BizServiceAppointment row = bizServiceAppointmentMapper.selectVetAppointmentByIdAndProvider(id, providerId);
        if (row == null)
        {
            throw new ServiceException("无权操作该预约记录");
        }
        return row;
    }

    private static void assertPendingForAction(BizServiceAppointment row, boolean confirm)
    {
        if (row.getStatus() == null)
        {
            throw new ServiceException(confirm ? "当前状态不允许确认接诊" : "当前状态不允许拒绝接诊");
        }
        if (row.getStatus() == ServiceAppointmentRules.STATUS_CANCELLED)
        {
            throw new ServiceException("该预约已取消，无法操作");
        }
        if (!ServiceAppointmentRules.canConfirmOrReject(row.getStatus()))
        {
            throw new ServiceException(confirm ? "当前状态不允许确认接诊" : "当前状态不允许拒绝接诊");
        }
    }

    private void throwStatusChanged(Long id, Long providerId, boolean confirm)
    {
        BizServiceAppointment latest = bizServiceAppointmentMapper.selectVetAppointmentByIdAndProvider(id, providerId);
        if (latest != null && latest.getStatus() != null
                && latest.getStatus() == ServiceAppointmentRules.STATUS_CANCELLED)
        {
            throw new ServiceException("该预约已取消，无法操作");
        }
        throw new ServiceException(confirm ? "当前状态不允许确认接诊" : "当前状态不允许拒绝接诊");
    }

    private static void assertCanComplete(BizServiceAppointment row)
    {
        if (row.getStatus() == null)
        {
            throw new ServiceException("当前状态不允许完成接诊");
        }
        if (row.getStatus() == ServiceAppointmentRules.STATUS_CANCELLED)
        {
            throw new ServiceException("该预约已取消，无法操作");
        }
        if (!ServiceAppointmentRules.canCompleteVetOrExpert(row.getStatus()))
        {
            throw new ServiceException("当前状态不允许完成接诊");
        }
    }

    private void throwCompleteNotAllowed(Long id, Long providerId)
    {
        BizServiceAppointment latest = bizServiceAppointmentMapper.selectVetAppointmentByIdAndProvider(id, providerId);
        if (latest != null && latest.getStatus() != null
                && latest.getStatus() == ServiceAppointmentRules.STATUS_CANCELLED)
        {
            throw new ServiceException("该预约已取消，无法操作");
        }
        throw new ServiceException("当前状态不允许完成接诊");
    }

    private static void enrichRow(BizServiceAppointment row)
    {
        if (row == null)
        {
            return;
        }
        row.setStatusLabel(VetAppointmentStatusResolver.resolveLabel(row.getStatus()));
        if (row.getStatus() != null)
        {
            row.setCanComplete(Boolean.valueOf(ServiceAppointmentRules.canCompleteVetOrExpert(row.getStatus())));
        }
    }
}
