package com.hzs.third.idcard.service.impl;

import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.hzs.common.core.constant.HttpStatus;
import com.hzs.common.core.domain.R;
import com.hzs.common.core.enums.EIdCardSide;
import com.hzs.common.core.enums.ESex;
import com.hzs.common.core.utils.DateUtils;
import com.hzs.third.idcard.dto.IdCardOcrDTO;
import com.hzs.third.idcard.service.IdCardService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

/**
 * 身份证接口
 */
@Slf4j
@Service
public class IdCardServiceImpl implements IdCardService {

    @Value("${idCardOcr.url}")
    private String url;

    @Value("${idCardOcr.appCode}")
    private String appCode;

    @Override
    public R<IdCardOcrDTO> invokeIdCardOcr(String idCardUrl, int side) {
        String authorization = "APPCODE " + appCode;
        HttpResponse response = HttpRequest.post(url)
                .header(Header.AUTHORIZATION, authorization)
                .header(Header.CONTENT_TYPE, "application/json; charset=UTF-8")
                .body(getInParam(idCardUrl, side))
                .timeout(10000)
                .execute();
        return parseResult(response, side);
    }

    /**
     * 解析返回的结果集
     *
     * @param response 响应信息
     * @return bankCardVO
     */
    private R<IdCardOcrDTO> parseResult(HttpResponse response, int side) {
        Integer status = response.getStatus();
        if (status.equals(HttpStatus.SUCCESS)) {
            String result = response.body();
            log.info("调用接口返回信息： " + result);
            JsonObject resultJson = JsonParser.parseString(result).getAsJsonObject();
            //识别结果，true表示成功，false表示失败
            boolean success = resultJson.get("success").getAsBoolean();
            if (success) {
                IdCardOcrDTO idCard = side == EIdCardSide.FACE.getValue() ? getIdCardFaceInfo(resultJson) : getIdCardBackInfo(resultJson);
                return R.ok(idCard);
            } else {
                String message = "调用接口解析失败";
                log.info("身份证ORC接口解析失败: {},信息为: {}", response.getStatus(), result);
                return R.fail(message);
            }
        } else {
            String message = (String) getErrorMessage().get(status);
            String result = message == null ? "请上传清晰的身份证图片" : message;
            log.info("身份证ORC接口异常返回状态值: {},信息为: {}", response.getStatus(), result);
            return R.fail(result);
        }
    }

    /**
     * 获取身份证的正面信息
     *
     * @param resultJson 返回的结果
     * @return IdCardOcrDTO
     */
    private IdCardOcrDTO getIdCardFaceInfo(JsonObject resultJson) {
        Integer sex = ESex.getLabel(resultJson.get("sex").getAsString());
        sex = sex == null ? ESex.UNKNOWN.getValue() : sex;
        return IdCardOcrDTO.builder()
                .name(resultJson.get("name").getAsString())
                .idCard(resultJson.get("num").getAsString())
                .sex(sex)
                .address(resultJson.get("address").getAsString())
                .build();
    }

    /**
     * 获取身份证的反面信息
     *
     * @param resultJson 返回的结果
     * @return IdCardOcrDTO
     */
    private IdCardOcrDTO getIdCardBackInfo(JsonObject resultJson) {
        String endDateJson = resultJson.get("end_date").getAsString();
        String endDate = endDateJson.equals("长期") ? LocalDate.now().plusYears(100).format(DateTimeFormatter.ofPattern(DateUtils.YAMMER)) : endDateJson;
        return IdCardOcrDTO.builder()
                .startDate(resultJson.get("start_date").getAsString())
                .endDate(endDate)
                .build();
    }

    /**
     * 获取入参
     *
     * @param idCardUrl 身体证照片地址
     * @return String
     */
    private String getInParam(String idCardUrl, int side) {
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("side", EIdCardSide.getLabel(side));
        jsonObject.addProperty("quality_info", false);
        JsonObject param = new JsonObject();
        param.addProperty("image", idCardUrl);
        param.addProperty("configure", jsonObject.toString());
        return param.toString();
    }

    /**
     * 错误信息
     *
     * @return Map
     */
    private Map<Integer, String> getErrorMessage() {
        Map<Integer, String> message = new HashMap<>();
        message.put(403, "购买次数用尽，或者URL错误");
        message.put(408, "超时");
        message.put(413, "上传身份证图片过大");
        message.put(461, "输入参数不符合要求");
        message.put(462, "请上传清晰的身份证图片");
        message.put(463, "请上传清晰的身份证图片");
        return message;
    }

}
