package com.ruoyi.web.modules.booking.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.booking.domain.AppMyAppointmentQuery;
import com.ruoyi.web.modules.booking.domain.AppMyAppointmentReviewBody;
import com.ruoyi.web.modules.booking.domain.vo.AppMyAppointmentListVo;
import com.ruoyi.web.modules.booking.mapper.AppMyAppointmentMapper;
import com.ruoyi.web.modules.booking.service.IAppMyAppointmentService;
import com.ruoyi.web.modules.booking.support.AppMyAppointmentQuerySupport;
import com.ruoyi.web.modules.booking.support.AppMyAppointmentReviewValidation;
import com.ruoyi.web.modules.booking.support.MyAppointmentStatusLabelResolver;
import com.ruoyi.web.modules.booking.support.MyAppointmentStatusTabRules;
import com.ruoyi.web.modules.diagnosis.domain.BizServiceAppointment;
import com.ruoyi.web.modules.diagnosis.support.ServiceAppointmentRules;
import com.ruoyi.web.modules.farming.domain.BizServiceAppointmentReview;
import com.ruoyi.web.modules.farming.mapper.BizServiceAppointmentReviewMapper;

/**
 * 移动端我的预约实现。
 */
@Service
public class AppMyAppointmentServiceImpl implements IAppMyAppointmentService
{
    @Autowired
    private AppMyAppointmentMapper appMyAppointmentMapper;

    @Autowired
    private BizServiceAppointmentReviewMapper bizServiceAppointmentReviewMapper;

    @Override
    public List<AppMyAppointmentListVo> selectMyAppointmentList(AppMyAppointmentQuery query)
    {
        if (query == null || StringUtils.isEmpty(query.getCreateBy()))
        {
            throw new ServiceException("请先登录");
        }
        List<AppMyAppointmentListVo> list = appMyAppointmentMapper.selectMyAppointmentList(query);
        if (list == null)
        {
            return new ArrayList<>();
        }
        for (AppMyAppointmentListVo row : list)
        {
            enrichListRow(row);
        }
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int cancelAppointment(Long id, String createBy, String updateBy)
    {
        BizServiceAppointment owned = loadOwned(id, createBy);
        if (!MyAppointmentStatusTabRules.canCancel(owned.getStatus()))
        {
            throw new ServiceException("当前状态不可取消预约");
        }
        int rows = appMyAppointmentMapper.cancelMyAppointment(id, createBy, updateBy != null ? updateBy : createBy);
        if (rows <= 0)
        {
            throw new ServiceException("取消失败，请刷新后重试");
        }
        return rows;
    }

    @Override
    public BizServiceAppointmentReview selectAppointmentReview(Long appointmentId, String createBy)
    {
        BizServiceAppointment owned = loadOwned(appointmentId, createBy);
        if (owned.getProviderType() == null
                || owned.getProviderType() != ServiceAppointmentRules.PROVIDER_TYPE_EXPERT)
        {
            throw new ServiceException("仅专家预约可查看评价");
        }
        if (owned.getStatus() == null || owned.getStatus() != ServiceAppointmentRules.STATUS_COMPLETED)
        {
            throw new ServiceException("仅已完成预约可查看评价");
        }
        List<BizServiceAppointmentReview> list =
                bizServiceAppointmentReviewMapper.selectReviewListByAppointmentId(appointmentId);
        if (list == null || list.isEmpty())
        {
            throw new ServiceException("暂无评价");
        }
        return list.get(0);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long submitAppointmentReview(Long appointmentId, AppMyAppointmentReviewBody body, String createBy,
            String reviewerName)
    {
        AppMyAppointmentReviewValidation.validate(body);
        BizServiceAppointment owned = loadOwned(appointmentId, createBy);
        if (owned.getProviderType() == null
                || owned.getProviderType() != ServiceAppointmentRules.PROVIDER_TYPE_EXPERT)
        {
            throw new ServiceException("仅专家预约可评价");
        }
        if (owned.getStatus() == null || owned.getStatus() != ServiceAppointmentRules.STATUS_COMPLETED)
        {
            throw new ServiceException("仅已完成预约可评价");
        }
        if (bizServiceAppointmentReviewMapper.countByAppointmentId(appointmentId) > 0)
        {
            throw new ServiceException("该预约已评价");
        }
        String name = StringUtils.isNotEmpty(reviewerName) ? reviewerName.trim() : createBy;
        if (StringUtils.isEmpty(name))
        {
            name = "用户";
        }
        BizServiceAppointmentReview review = new BizServiceAppointmentReview();
        review.setAppointmentId(appointmentId);
        review.setReviewerName(name);
        review.setReviewTime(new Date());
        review.setPunctualityScore(body.getPunctualityScore());
        review.setAttitudeScore(body.getAttitudeScore());
        review.setGuidanceScore(body.getGuidanceScore());
        review.setSummary(body.getSummary());
        int n = bizServiceAppointmentReviewMapper.insertBizServiceAppointmentReview(review);
        if (n <= 0 || review.getId() == null)
        {
            throw new ServiceException("评价提交失败");
        }
        return review.getId();
    }

    private BizServiceAppointment loadOwned(Long id, String createBy)
    {
        if (id == null)
        {
            throw new ServiceException("预约记录不存在");
        }
        if (StringUtils.isEmpty(createBy))
        {
            throw new ServiceException("请先登录");
        }
        BizServiceAppointment row = appMyAppointmentMapper.selectMyAppointmentByIdAndUser(id, createBy);
        if (row == null)
        {
            throw new ServiceException("预约记录不存在");
        }
        return row;
    }

    private static void enrichListRow(AppMyAppointmentListVo row)
    {
        if (row.getStatus() != null && row.getProviderType() != null)
        {
            row.setStatusLabel(MyAppointmentStatusLabelResolver.resolve(row.getProviderType(), row.getStatus()));
            row.setCanCancel(MyAppointmentStatusTabRules.canCancel(row.getStatus()));
        }
        if (row.getHasReview() == null)
        {
            row.setHasReview(Boolean.FALSE);
        }
    }
}
