package com.yd.csf.api.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yd.common.exception.BusinessException;
import com.yd.common.result.Result;
import com.yd.csf.api.service.ApiAppointmentService;
import com.yd.csf.feign.client.appointment.ApiAppointmentFeignClient;
import com.yd.csf.feign.dto.appointment.ApiAppointmentInfoDto;
import com.yd.csf.feign.dto.appointment.ApiInsurantInfoDto;
import com.yd.csf.feign.request.appointment.*;
import com.yd.csf.feign.response.appointment.*;
import com.yd.csf.feign.valid.GroupValid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import javax.validation.constraints.NotBlank;
import java.util.Objects;
import java.util.Set;

/**
 * 预约信息
 *
 * @author zxm
 * @since 2025-09-01
 */
@RestController
@RequestMapping("/appointment")
@Validated
public class ApiAppointmentController implements ApiAppointmentFeignClient {

    @Autowired
    private ApiAppointmentService apiAppointmentService;

    private final Validator validator;
    public ApiAppointmentController(Validator validator) {
        this.validator = validator;
    }

    /**
     * 预约分页查询
     * @param request
     * @return
     */
    @Override
    public Result<IPage<ApiAppointmentPageResponse>> page(ApiAppointmentPageRequest request) {
        return apiAppointmentService.page(request);
    }

    /**
     * 预约详情（聚合信息详情）
     * @param appointmentBizId
     * @return
     */
    @Override
    public Result<ApiAppointmentDetailResponse> detail(String appointmentBizId) {
        return apiAppointmentService.detail(appointmentBizId);
    }

    /**
     * 预约主体信息详情（单个对象详情）
     * @param appointmentBizId
     * @return
     */
    @Override
    public Result<ApiAppointmentInfoDto> mainDetail(String appointmentBizId) {
        return apiAppointmentService.mainDetail(appointmentBizId);
    }

    /**
     * 新增预约提交 (聚合信息新增预约提交)
     * @param request
     * @return
     */
    @Override
    public Result<ApiAppointmentAddResponse> add(ApiAppointmentAddRequest request) {
        //手动校验受保人信息（因为它没有 @Valid 注解）
        ApiInsurantInfoDto insurantInfo = request.getApiInsurantInfoDto();
        validateInsurantInfo(insurantInfo);

        return apiAppointmentService.add(request);
    }

    /**
     * 新增预约暂存
     * @param request
     * @return
     */
    @Override
    public Result addStorage(ApiAppointmentAddStorageRequest request) {
        return apiAppointmentService.addStorage(request);
    }

    /**
     * 编辑预约提交 (聚合信息编辑预约提交)
     * @param request
     * @return
     */
    @Override
    public Result edit(ApiAppointmentEditRequest request) {
        //手动校验受保人信息（因为它没有 @Valid 注解）
        ApiInsurantInfoDto insurantInfo = request.getApiInsurantInfoDto();
        validateInsurantInfo(insurantInfo);

        return apiAppointmentService.edit(request);
    }

    /**
     * 编辑预约暂存 (聚合信息编辑预约暂存)
     * @param request
     * @return
     */
    @Override
    public Result editStorage(ApiAppointmentEditStorageRequest request) {
        return apiAppointmentService.editStorage(request);
    }

    /**
     * 确定预约时间提交 (流程流转到新单跟进)
     * @param request
     * @return
     */
    @Override
    public Result editConfirmTime(ApiAppointmentEditConfirmTimeRequest request) {
        return apiAppointmentService.editConfirmTime(request);
    }

    /**
     * 单个对象编辑-编辑预约主体信息
     * @param apiAppointmentInfoDto
     * @return
     */
    @Override
    public Result singleEdit(ApiAppointmentInfoDto apiAppointmentInfoDto) {
        return apiAppointmentService.singleEdit(apiAppointmentInfoDto);
    }

    /**
     * 预约编辑关联FNA
     * @param request
     * @return
     */
    @Override
    public Result editFna(ApiAppointmentEditFnaRequest request) {
        return apiAppointmentService.editFna(request);
    }

    /**
     * 预约解除关联FNA
     * @param request
     * @return
     */
    @Override
    public Result removeFna(ApiAppointmentRemoveFnaRequest request) {
        return apiAppointmentService.removeFna(request);
    }

    /**
     * 预约编辑关联计划书
     * @param request
     * @return
     */
    @Override
    public Result editProposal(ApiAppointmentEditProposalRequest request) {
        return apiAppointmentService.editProposal(request);
    }

    /**
     * 预约解除关联计划书
     * @param request
     * @return
     */
    @Override
    public Result removeProposal(ApiAppointmentRemoveProposalRequest request) {
        return apiAppointmentService.removeProposal(request);
    }

    /**
     * 预约编辑转保声明
     * @param request
     * @return
     */
    @Override
    public Result editPolicyTransfer(ApiPolicyTransferRequest request) {
        return apiAppointmentService.editPolicyTransfer(request);
    }

    /**
     * 编辑预约状态
     * @param request
     * @return
     */
    @Override
    public Result editStatus(ApiAppointmentEditStatusRequest request) {
        return apiAppointmentService.editStatus(request);
    }

    /**
     * 删除预约信息
     * @param appointmentBizId
     * @return
     */
    @Override
    public Result del(String appointmentBizId) {
        return apiAppointmentService.del(appointmentBizId);
    }

    /**
     * 历史记录 - 签约信息
     * @param request
     * @return
     */
    @Override
    public Result<IPage<ApiAppointmentLogPageResponse>> logPage(ApiAppointmentLogPageRequest request) {
        return apiAppointmentService.logPage(request);
    }

    /**
     * 历史记录 - 签约信息 - 详情
     * @param appointmentLogBizId
     * @return
     */
    @Override
    public Result<ApiAppointmentLogDetailResponse> logDetail(String appointmentLogBizId) {
        return apiAppointmentService.logDetail(appointmentLogBizId);
    }

    /**
     * 手动校验受保人信息
     * @param insurantInfo
     */
    private void validateInsurantInfo(ApiInsurantInfoDto insurantInfo) {
        if (Objects.isNull(insurantInfo)) {
            throw new BusinessException("受保人信息不能为空");
        }

        // 根据与投保人关系选择校验组
        Class<?>[] groups;
        if (insurantInfo.isSelf()) {
            // 本人关系：只校验 Always 组
            groups = new Class<?>[]{GroupValid.Always.class};
        } else {
            // 非本人关系：校验 Always 和 NotSelf 组
            groups = new Class<?>[]{GroupValid.Always.class, GroupValid.NotSelf.class};
        }

        // 执行手动校验
        Set<ConstraintViolation<ApiInsurantInfoDto>> violations =
                validator.validate(insurantInfo, groups);

        // 如果校验失败，抛出业务异常
        if (!violations.isEmpty()) {
            String errorMessage = violations.iterator().next().getMessage();
            throw new BusinessException(errorMessage);
        }
    }

}
