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

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
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.web.modules.diagnosis.domain.BizServiceAppointment;
import com.ruoyi.web.modules.diagnosis.mapper.BizServiceAppointmentMapper;
import com.ruoyi.web.modules.diagnosis.service.IBizOrgMyAppointmentService;
import com.ruoyi.web.modules.diagnosis.support.OrgAppointmentStatusResolver;
import com.ruoyi.web.modules.diagnosis.support.OrgAppointmentValidation;
import com.ruoyi.web.modules.diagnosis.support.OrgProviderResolver;
import com.ruoyi.web.modules.diagnosis.support.ServiceAppointmentRules;

/**
 * 我的预约（机构）服务实现。
 */
@Service
public class BizOrgMyAppointmentServiceImpl implements IBizOrgMyAppointmentService
{
    @Autowired
    private BizServiceAppointmentMapper bizServiceAppointmentMapper;

    @Autowired
    private OrgProviderResolver orgProviderResolver;

    @Override
    public List<BizServiceAppointment> selectOrgAppointmentList(BizServiceAppointment query, Long sysUserId)
    {
        Long providerId = orgProviderResolver.resolveProviderId(sysUserId);
        if (providerId == null)
        {
            return new ArrayList<>();
        }
        OrgAppointmentValidation.validateListQuery(query);
        BizServiceAppointment criteria = query != null ? query : new BizServiceAppointment();
        criteria.setProviderType(ServiceAppointmentRules.PROVIDER_TYPE_ORG);
        criteria.setProviderId(providerId);
        List<BizServiceAppointment> list = bizServiceAppointmentMapper.selectOrgAppointmentList(criteria);
        if (list == null || list.isEmpty())
        {
            return new ArrayList<>();
        }
        list = new ArrayList<>(list);
        Iterator<BizServiceAppointment> it = list.iterator();
        while (it.hasNext())
        {
            BizServiceAppointment row = it.next();
            if (row.getStatus() != null && !ServiceAppointmentRules.isOrgStatusVisible(row.getStatus()))
            {
                it.remove();
                continue;
            }
            enrichRow(row);
        }
        return list;
    }

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

    @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.updateCompleteOrgAppointment(patch);
        if (rows <= 0)
        {
            throwCompleteNotAllowed(owned.getId(), owned.getProviderId());
        }
        return rows;
    }

    private BizServiceAppointment loadOwnedRow(Long id, Long sysUserId)
    {
        return loadOwnedRow(id, sysUserId, false);
    }

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

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

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

    private static void assertOrgStatusVisible(BizServiceAppointment row)
    {
        if (row.getStatus() == null || !ServiceAppointmentRules.isOrgStatusVisible(row.getStatus()))
        {
            throw new ServiceException("预约数据状态异常，请联系管理员");
        }
    }

    private static void enrichRow(BizServiceAppointment row)
    {
        if (row == null)
        {
            return;
        }
        row.setStatusLabel(OrgAppointmentStatusResolver.resolveLabel(row.getStatus()));
        row.setRejectReason(null);
        row.setConfirmTime(null);
        row.setRejectTime(null);
        if (row.getStatus() != null)
        {
            row.setCanComplete(Boolean.valueOf(ServiceAppointmentRules.canCompleteOrg(row.getStatus())));
        }
    }
}
