package com.ywt.outpatient.controllers;

import com.ywt.biz.common.constant.YwtCommonRespCode;
import com.ywt.biz.common.enums.SexEnum;
import com.ywt.biz.common.exception.YwtCommonException;
import com.ywt.biz.common.util.Checker;
import com.ywt.biz.common.util.DateUtil;
import com.ywt.biz.common.util.PhoneNumChecker;
import com.ywt.biz.common.util.serializers.JsonSerializer;
import com.ywt.gapi.taihe.biz.*;
import com.ywt.outpatient.api.req.MriBookingReq;
import com.ywt.outpatient.api.resp.BaseResponse2;
import com.ywt.outpatient.api.resp.GetAvailableBookCountResp;
import com.ywt.outpatient.api.resp.SubmitScreeningTableResp;
import com.ywt.outpatient.core.BaseResponse;
import com.ywt.outpatient.core.utils.CheckUtil;
import com.ywt.outpatient.api.mri.QuestionOption;
import com.ywt.outpatient.api.mri.ScreeningTable;
import com.ywt.outpatient.service.web.UserSrv;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Walker
 * Created on 2020/7/14
 */
@RestController("/taihe/mri")
@RequestMapping(value = {"/taihe/mri"})
public class MriController {
    private final Logger logger = LoggerFactory.getLogger(MriController.class);

    @DubboReference
    private TaiheBizService taiheBizServiceBlockingStub;

    @Autowired
    private UserSrv userSrv;

    @RequestMapping(value = {"/book"}, method = RequestMethod.POST)
    public @ResponseBody
    BaseResponse2<Void> book(@RequestBody MriBookingReq reqData) {
        BaseResponse2<Void> baseResponse = new BaseResponse2<>();
        try {
            String name = reqData.getName();
            Integer sex = reqData.getSex();
            String mobile = reqData.getMobile();
            String date = reqData.getDate();
            int userId = userSrv.getCurrentUserIdWrapped();
            CheckUtil.ensureLargerThanZero(userId, "请登录后操作");
            CheckUtil.ensureLargerThanZero(sex, "性别未完善，请完善");
            CheckUtil.ensureNotEmpty(name, "姓名未完善，请完善");
            CheckUtil.ensureNotEmpty(mobile, "手机号未完善，请完善");
            CheckUtil.ensureNotEmpty(date, "预约日期未完善，请完善");
            SexEnum sexEnum = SexEnum.valueOf(sex);
            if (sexEnum == null) throw new YwtCommonException(YwtCommonRespCode.P_ERR, "请选择性别");
            Date d = DateUtil.parseDate(date, "yyyy-MM-dd");
            if (d == null) throw new YwtCommonException(YwtCommonRespCode.P_ERR, "日期格式不正确");
            if (!PhoneNumChecker.isPhoneNum(mobile)) throw new YwtCommonException(YwtCommonRespCode.P_ERR, "手机号格式不正确");
            MriBookingRequest request = MriBookingRequest.newBuilder()
                    .setUserId(userId)
                    .setName(name)
                    .setSex(sex)
                    .setMobile(mobile)
                    .setDate(date)
                    .build();
            MriBaseResponse response = taiheBizServiceBlockingStub.mriBooking(request);
            if (response.getCode() == BaseResponse.SUCCEED) {
                return baseResponse.succeed("提交成功");
            }
            return baseResponse.failed(BaseResponse.APP_ERROR, response.getInfo());
        } catch (YwtCommonException appMessageException) {
            return baseResponse.error(appMessageException.getMessage());
        } catch (Exception e) {
            logger.error("MriController#book(): {}", e.getMessage(), e);
            return baseResponse.error(e.getMessage());
        }
    }

    @RequestMapping(value = {"/screeningTable"}, method = RequestMethod.POST)
    public @ResponseBody
    BaseResponse2<ScreeningTable> screeningTable() {
        BaseResponse2<ScreeningTable> baseResponse = new BaseResponse2<>();
        try {
            int userId = userSrv.getCurrentUserIdWrapped();
            CheckUtil.ensureLargerThanZero(userId, "请登录后操作");
            GetScreeningTableRequest getScreeningTableRequest = GetScreeningTableRequest.newBuilder()
                    .setUserId(userId)
                    .build();
            GetScreeningTableResponse response = taiheBizServiceBlockingStub.getScreeningTable(getScreeningTableRequest);
            if (response.getCode() == BaseResponse.SUCCEED) {
                ScreeningTable resp = new ScreeningTable();
                com.ywt.gapi.taihe.biz.ScreeningTable table = response.getScreeningTable();
                if (table != null) {
                    com.ywt.gapi.taihe.biz.PatientInfo info = table.getPatientInfo();
                    com.ywt.outpatient.api.mri.PatientInfo patientInfo = new com.ywt.outpatient.api.mri.PatientInfo();
                    if (info != null) {
                        patientInfo.setPatientName(info.getPatientName());
                        patientInfo.setSex(info.getSex());
                        patientInfo.setBirthday(info.getBirthday());
                        patientInfo.setPatientMobile(info.getPatientMobile());
                        patientInfo.setAddress(info.getAddress());
                    }
                    List<com.ywt.outpatient.api.mri.Question> questions = table.getQuestionsList().stream()
                            .map(question -> {
                                com.ywt.outpatient.api.mri.Question q = new com.ywt.outpatient.api.mri.Question();
                                q.setQuestionId(question.getQuestionId());
                                q.setCategory(question.getCategory());
                                q.setOptions(convertGrpcDefObj2Model(question.getOptionsList()));
                                return q;
                            })
                            .collect(Collectors.toList());
                    resp.setPatientInfo(patientInfo);
                    resp.setQuestions(questions);
                    resp.setTableId(table.getTableId());
                }
                return baseResponse.succeed(resp);
            }
            return baseResponse.failed(BaseResponse.APP_ERROR, response.getMsg());
        } catch (YwtCommonException appMessageException) {
            return baseResponse.error(appMessageException.getMessage());
        } catch (Exception e) {
            logger.error("MriController#screeningTable(): {}", e.getMessage(), e);
            return baseResponse.error(e.getMessage());
        }
    }

    private List<QuestionOption> convertGrpcDefObj2Model(List<com.ywt.gapi.taihe.biz.QuestionOption> list) {
        return list.stream()
                .map(questionOption -> {
                    QuestionOption option = new QuestionOption();
                    List<com.ywt.gapi.taihe.biz.QuestionOption> subList = questionOption.getChildrenList();
                    List<QuestionOption> children = new LinkedList<>();
                    if (subList != null && !subList.isEmpty()) {
                        children = convertGrpcDefObj2Model(subList);
                    }
                    option.setId(questionOption.getId());
                    option.setName(questionOption.getName());
                    option.setValue1(questionOption.getValue1());
                    option.setValue2(questionOption.getValue2());
                    option.setValue3(questionOption.getValue3());
                    option.setChildren(children);
                    return option;
                })
                .collect(Collectors.toList());
    }

    private List<com.ywt.gapi.taihe.biz.QuestionOption> convertModel2GrpcDefObj(List<QuestionOption> list) {
        return list.stream()
                .map(questionOption -> {
                    List<com.ywt.gapi.taihe.biz.QuestionOption> options = new LinkedList<>();
                    List<QuestionOption> children = questionOption.getChildren();
                    if (children != null && !children.isEmpty()) {
                        options = convertModel2GrpcDefObj(children);
                    }
                    return com.ywt.gapi.taihe.biz.QuestionOption.newBuilder()
                            .setId(Checker.getIntegerValue(questionOption.getId()))
                            .setName(Checker.getStringValue(questionOption.getName()))
                            .setValue1(Checker.getBooleanValue(questionOption.getValue1()))
                            .setValue2(Checker.getStringValue(questionOption.getValue2()))
                            .setValue3(Checker.getStringValue(questionOption.getValue3()))
                            .addAllChildren(options)
                            .build();
                })
                .collect(Collectors.toList());
    }

    @RequestMapping(value = {"/submitTable"}, method = RequestMethod.POST)
    public @ResponseBody
    BaseResponse2<SubmitScreeningTableResp> submitTable(@RequestBody ScreeningTable reqData) {
        BaseResponse2<SubmitScreeningTableResp> baseResponse = new BaseResponse2<>();
        try {
            int userId = userSrv.getCurrentUserIdWrapped();
            CheckUtil.ensureLargerThanZero(userId, "请登录后操作");
            com.ywt.outpatient.api.mri.PatientInfo patientInfo = reqData.getPatientInfo();
            if (patientInfo == null) throw new YwtCommonException(YwtCommonRespCode.P_ERR, "请完善信息");
            int sex = patientInfo.getSex();
            CheckUtil.ensureLargerThanZero(sex, "性别未完善，请完善");
            String patientName = patientInfo.getPatientName();
            CheckUtil.ensureNotEmpty(patientName, "姓名未完善，请完善");
            CheckUtil.ensureStringLength(patientName, 10, "姓名10个汉字内");
            String patientMobile = patientInfo.getPatientMobile();
            CheckUtil.ensureNotEmpty(patientMobile, "手机号未完善，请完善");
            String birthday = patientInfo.getBirthday();
            CheckUtil.ensureNotEmpty(birthday, "出生年月未完善，请完善");
            Date d = DateUtil.parseDate(birthday, "yyyy-MM-dd");
            if (d == null) throw new YwtCommonException(YwtCommonRespCode.P_ERR, "出生年月日期格式不正确");
            String address = patientInfo.getAddress();
            CheckUtil.ensureNotEmpty(address, "家庭住址未完善，请完善");
            CheckUtil.ensureStringLength(address, 100, "家庭住址最多100个汉字");
            SexEnum sexEnum = SexEnum.valueOf(sex);
            if (sexEnum == null) throw new YwtCommonException(YwtCommonRespCode.P_ERR, "请选择性别");
            if (!PhoneNumChecker.isPhoneNum(patientMobile)) throw new YwtCommonException(YwtCommonRespCode.P_ERR, "手机号格式不正确");
            // 患者信息
            com.ywt.gapi.taihe.biz.PatientInfo info = com.ywt.gapi.taihe.biz.PatientInfo.newBuilder()
                    .setAddress(address)
                    .setBirthday(birthday)
                    .setPatientMobile(patientMobile)
                    .setPatientName(patientName)
                    .setSex(sex)
                    .build();
            List<com.ywt.outpatient.api.mri.Question> questions = reqData.getQuestions();
            if (Checker.isNone(questions)) questions = new LinkedList<>();
            List<com.ywt.gapi.taihe.biz.Question> questionList = questions.stream()
                    .map(question -> com.ywt.gapi.taihe.biz.Question.newBuilder()
                            .setCategory(Checker.getStringValue(question.getCategory()))
                            .setQuestionId(Checker.getIntegerValue(question.getQuestionId()))
                            .addAllOptions(convertModel2GrpcDefObj(question.getOptions()))
                            .build())
                    .collect(Collectors.toList());
            com.ywt.gapi.taihe.biz.ScreeningTable table = com.ywt.gapi.taihe.biz.ScreeningTable.newBuilder()
                    .setPatientInfo(info)
                    .addAllQuestions(questionList)
                    .setTableId(reqData.getTableId())
                    .build();
            SubmitScreeningTableRequest request = SubmitScreeningTableRequest.newBuilder()
                    .setTable(table)
                    .setUserId(userId)
                    .setSubmitContent(JsonSerializer.toJson(reqData))
                    .setCompleted(reqData.isCompleted())
                    .build();
            SubmitScreeningTableResponse response = taiheBizServiceBlockingStub.submitScreeningTable(request);
            if (response.getCode() == BaseResponse.SUCCEED) {
                SubmitScreeningTableResp resp = new SubmitScreeningTableResp();
                resp.setTableId(response.getTableId());
                return baseResponse.succeed(resp);
            }
            return baseResponse.failed(BaseResponse.APP_ERROR, response.getMsg());
        } catch (YwtCommonException appMessageException) {
            return baseResponse.error(appMessageException.getMessage());
        } catch (Exception e) {
            logger.error("MriController#submitTable(): {}", e.getMessage(), e);
            return baseResponse.error(e.getMessage());
        }
    }

    @RequestMapping(value = {"/getAvailableBookNum"}, method = RequestMethod.POST)
    public @ResponseBody
    BaseResponse2<GetAvailableBookCountResp> getAvailableBookNum(@RequestBody MriBookingReq reqData) {
        BaseResponse2<GetAvailableBookCountResp> baseResponse = new BaseResponse2<>();
        try {
            String date = reqData.getDate();
            CheckUtil.ensureNotEmpty(date, "预约日期未完善，请完善");
            GetAvailableBookNumResponse response = taiheBizServiceBlockingStub.getAvailableBookNum(
                    GetAvailableBookNumRequest.newBuilder()
                            .setDate(date)
                            .build());
            if (response.getCode() == BaseResponse.SUCCEED) {
                GetAvailableBookCountResp resp = new GetAvailableBookCountResp();
                resp.setCount(response.getCount());
                return baseResponse.succeed(resp);
            }
            return baseResponse.failed(BaseResponse.APP_ERROR, response.getMsg());
        } catch (YwtCommonException appMessageException) {
            return baseResponse.error(appMessageException.getMessage());
        } catch (Exception e) {
            logger.error("MriController#getAvailableBookNum(): {}", e.getMessage(), e);
            return baseResponse.error(e.getMessage());
        }
    }
}
