package com.jeequan.jeepay.thirdparty.service.ocr;

import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.exception.BizException;
import lombok.AllArgsConstructor;
import lombok.Cleanup;
import lombok.Data;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

/**
 * TODO
 *
 * @author crystal
 * @date 2023/10/24 16:08
 */
@Slf4j
@Data
public class BaiduClient {

    private String apiKey;

    private String secretKey;

    private String accessToken;

    /**
     * accessToken 获取url
     */
    private final String AUTH_URL = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=CLIENT_ID&client_secret=CLIENT_SECRET";

    /**
     * 营业执照url
     */
    private final String BL_CARD_URL = "https://aip.baidubce.com/rest/2.0/ocr/v1/business_license?access_token=ACCESS_TOKEN";

    /**
     * 身份证识别url
     */
    private final String ID_CARD_URL = "https://aip.baidubce.com/rest/2.0/ocr/v1/idcard?access_token=ACCESS_TOKEN";

    /**
     * 银行卡识别url
     */
    private final String BK_CARD_URL = "https://aip.baidubce.com/rest/2.0/ocr/v1/bankcard?access_token=ACCESS_TOKEN";

    public final String CLIENT_ID_NAME = "CLIENT_ID";

    public final String CLIENT_SECRET_NAME = "CLIENT_SECRET";

    public final String BAUDU_AUTH_TOKEN_NAME = "ACCESS_TOKEN";

    public final String BAUDU_ERROR_CODE = "error_code";

    public final String BAUDU_ERROR_DESC = "error_description";

    public final String ACCESS_TOKEN_CODE = "access_token";

    public final Integer DEFAULT_EXPIRE_NUM = 30;


    @Data
    public class IdCard {
        /**
         * 名字
         */
        public String name;

        /**
         * 号码
         */
        public String idNum;

        public String sex;
        /**
         * 有效期
         */
        public String validDate;

        public String address;
    }

    @Data
    public class BusinessLicence {
        /**
         * 营业执照编号
         */
        public String busNo;

        /**
         * 营业执照名称
         */
        public String name;

        /**
         * 法人姓名
         */
        public String person;

        /**
         * 有效期
         */
        public String address;

        /**
         * 经营范围
         */
        public String business;

        /**
         * 有效期
         */
        public String startDate;

        /**
         * 截止日期
         */
        public String endDate;

        public BusinessLicence(String busNo, String name, String person, String address, String startDate, String endDate, String business) {
            this.busNo = busNo;
            this.name = name;
            this.person = person;
            this.address = address;
            this.startDate = startDate;
            this.endDate = endDate;
            this.business = business;
        }
    }

    @Data
    public class BankCard {
        /**
         * 银行名称
         */
        public String bankName;

        /**
         * 卡号
         */
        public String cardNo;

        public BankCard(String bankName, String cardNo) {
            this.bankName = bankName;
            this.cardNo = cardNo;
        }
    }

    @Getter
    @AllArgsConstructor
    public enum BankCardStatus {

        NO(0, "当前卡片无法识别，请上传比较清晰的图片！"),
        DEBIT_CARD(1, "借记卡"),
        CREDIT_CARD(2, "贷记卡"),
        ZHUN_CREDIT_CARD(3, "准贷记卡"),
        PREPAID_CARD(4, "预付费卡");

        private int value;

        private String desc;

        public static void checkCardType(int value) {
            boolean flag = false;
            String text = "";
            if (value == NO.getValue()) {
                text = NO.getDesc();
            } else {
                BankCardStatus[] values = values();
                for (BankCardStatus val : values) {
                    if (val.getValue() == value) {
                        flag = true;
                    } else {
                        text = "只能上传" + DEBIT_CARD.getDesc();
                    }
                }
            }
            if (!flag) {
                throw new BizException(text);
            }
        }
    }

    public BaiduClient(String apiKey, String secretKey) {
        this.apiKey = apiKey;
        this.secretKey = secretKey;
        this.accessToken = getAuthAccessToken();
    }

    /**
     * 获取授权token
     *
     * @return
     */
    public String getAuthAccessToken() {
        String reqUrl = AUTH_URL.replace(CLIENT_ID_NAME, this.getApiKey()).replace(CLIENT_SECRET_NAME, this.getSecretKey());
        String body = HttpRequest.get(reqUrl).execute().body();
        if (StringUtils.isEmpty(body)) {
            throw new BizException("百度授权接口异常");
        }
        JSONObject result = JSON.parseObject(body);
        String access_token = result.getString(ACCESS_TOKEN_CODE);
        if (StringUtils.isEmpty(access_token)) {
            throw new BizException("百度授权接口异常，异常信息：" + result.getString(BAUDU_ERROR_DESC));
        }
        return access_token;
    }

    /**
     * 营业执照OCR
     *
     * @param url
     * @return
     */
    public BusinessLicence blOCR(String url) {
        String reqUrl = BL_CARD_URL.replace(BAUDU_AUTH_TOKEN_NAME, this.getAccessToken());
        String body;
        try {
            @Cleanup HttpResponse execute = HttpRequest.post(reqUrl)
                    .form("url", url)
                    .execute();
            body = execute.body();
        } catch (Exception e) {
            log.info("OCR接口异常", e);
            throw new BizException("OCR接口异常, 请联系平台管理人员");
        }

        try {
            JSONObject result = initResult(body);
            String name = result.getJSONObject("单位名称").getString("words");
            String person = result.getJSONObject("法人").getString("words");
            String busNo = result.getJSONObject("社会信用代码").getString("words");
            String business = result.getJSONObject("经营范围").getString("words");
            String address = result.getJSONObject("地址").getString("words");
            String startDate = DateUtil.format(DateUtil.parse(result.getJSONObject("成立日期").getString("words"), "yyyy年MM月dd日"), "yyyy-MM-dd");
            String endDate = result.getJSONObject("有效期").getString("words");
            if (StringUtils.isNotEmpty(endDate) && "无".equals(endDate)) {
                endDate = "长期";
            }
            BusinessLicence bl = new BusinessLicence(busNo, name, person, address, startDate, endDate, business);

            return bl;
        } catch (Exception e) {
            log.info("OCR识别失败", e);
            throw new BizException("OCR识别失败, 请手动相关补充资料");
        }
    }

    /**
     * 身份证OCR
     *
     * @param url
     * @return
     */
    public IdCard icOCR(String url) {
        String reqUrl = ID_CARD_URL.replace(BAUDU_AUTH_TOKEN_NAME, this.getAccessToken());
        String body;
        try {
            @Cleanup HttpResponse execute = HttpRequest.post(reqUrl)
                    .form("url", url)
                    .form("id_card_side", "front")
                    .execute();
            body = execute.body();
        } catch (Exception e) {
            log.info("OCR接口异常", e);
            throw new BizException("OCR接口异常, 请联系平台管理人员");
        }

        JSONObject result = initResult(body);
        JSONObject nameObj = result.getJSONObject("姓名");
        IdCard idCard = new IdCard();
        try {
            if (nameObj != null) {
                String cardName = nameObj.getString("words");
                String cardNo = result.getJSONObject("公民身份号码").getString("words");
                String address = result.getJSONObject("住址").getString("words");
                idCard.setName(cardName);
                idCard.setIdNum(cardNo);
                idCard.setAddress(address);
                return idCard;
            } else {
                String startDate = result.getJSONObject("签发日期").getString("words");
                String endDate = result.getJSONObject("失效日期").getString("words");
                idCard.setValidDate(startDate + "-" + endDate);
                return idCard;
            }
        } catch (Exception e) {
            log.info("OCR识别失败", e);
            throw new BizException("OCR识别失败, 请手动相关补充资料");
        }
    }

    /**
     * 银行卡OCR
     *
     * @param url
     * @return
     */
    public BankCard bkOCR(String url) {

        String reqUrl = BK_CARD_URL.replace(BAUDU_AUTH_TOKEN_NAME, this.getAccessToken());
        String body;
        try {
            @Cleanup HttpResponse execute = HttpRequest.post(reqUrl)
                    .form("url", url)
                    .execute();
            body = execute.body();
        } catch (Exception e) {
            log.info("OCR接口异常", e);
            throw new BizException("OCR接口异常, 请联系平台管理人员");
        }

        try {
            JSONObject result = initResult(body);
            int cardType = result.getIntValue("bank_card_type");
            BankCardStatus.checkCardType(cardType);
            String cardNo = result.getString("bank_card_number").replaceAll("\\s", "");
            String bankName = result.getString("bank_name");
            return new BankCard(bankName, cardNo);
        } catch (Exception e) {
            log.info("OCR识别失败", e);
            throw new BizException("OCR识别失败, 请手动相关补充资料");
        }
    }

    private JSONObject initResult(String body) {
        if (StringUtils.isEmpty(body)) {
            throw new BizException("百度OCR识别接口异常");
        }
        JSONObject resObj = JSON.parseObject(body);
        if (resObj.containsKey(BAUDU_ERROR_CODE)) {
            throw new BizException("百度OCR识别接口异常，异常信息:" + resObj.getString(BAUDU_ERROR_DESC));
        }
        JSONObject words_result = resObj.getJSONObject("words_result");
        if (words_result == null) {
            JSONObject res = resObj.getJSONObject("result");
            return res;
        }
        return words_result;
    }
}
