package com.xinelu.web.controller.fd;

import com.alibaba.fastjson2.JSONObject;
import com.xinelu.common.core.controller.BaseController;
import com.xinelu.common.core.domain.R;
import com.xinelu.common.exception.ServiceException;
import com.xinelu.common.utils.DateUtils;
import com.xinelu.common.utils.http.HttpService;
import com.xinelu.common.utils.http.SslUtils;
import com.xinelu.familydoctor.applet.pojo.body.DzsCodeBody;
import com.xinelu.familydoctor.applet.pojo.query.DzsCodeQuery;
import com.xinelu.web.controller.fd.utils.DzsCodeSign;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Api(tags = "德州市居民码控制器（爱山东APP）")
@Slf4j
@RestController
@RequestMapping("/applet/fd/dzs/code")
public class DzsCodeController extends BaseController {

    @Resource
    private HttpService httpService;
    @Value("${dzsCode.appid}")
    private String appid;
    @Value("${dzsCode.appSecret}")
    private String appSecret;
    @Value("${dzsCode.url}")
    private String url;
    @Value("${dzsCode.mutualUrl}")
    private String mutualUrl;
    @Value("${dzsCode.isSecret}")
    private String isSecret;
    @Value("${dzsCode.isWhole}")
    private String isWhole;
    @Value("${dzsCode.institutionCode}")
    private String institutionCode;
    @Value("${dzsCode.useCityCode}")
    private String useCityCode;
    @Value("${dzsCode.businessStepCode}")
    private String businessStepCode;

    @ApiOperation(value = "居民码注册接口")
    @GetMapping("/register")
    public R<?> register(DzsCodeBody body) {
        try {
            JSONObject bodyParams = registerBody(body);
            String message = "";
            // 0：明文 1：加密
            if (isSecret.equals("1")) {
                message = DzsCodeSign.makeSign(appSecret, bodyParams.toJSONString());
            } else {
                message = bodyParams.toJSONString();
            }
            Map<String, Object> headerMap = headerParams(message);
            // 0：明文 1：加密
            JSONObject requestBody = new JSONObject();
            requestBody.put("message", message);
            SslUtils.ignoreSsl();
            JSONObject resultObj = httpService.post(url + "/register", headerMap, requestBody);
            log.info("居民码注册接口响应：{}", resultObj);
            if (!resultObj.containsKey("code") || !resultObj.getString("code").equals("200")) {
                if (resultObj.containsKey("msg") && !StringUtils.isBlank(resultObj.getString("msg"))) {
                    return R.fail(resultObj.getString("msg"));
                }
                return R.fail("接口异常");
            }
            if (resultObj.containsKey("data")) {
                return R.ok(resultObj.get("data"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
        return R.ok();
    }

    @ApiOperation(value = "居民码查询接口")
    @GetMapping("/analysis")
    public R<?> query(DzsCodeQuery queryBody) {
        try {
            JSONObject bodyParams;
            switch (queryBody.getInterfaceName()) {
                // 是否已注册
                case "isReg":
                    bodyParams = isRegBody(queryBody.getCardType(), queryBody.getCardNo());
                    break;
                // 根据UID获取码值
                case "getCodeByUid":
                    bodyParams = getCodeByUidBody(queryBody.getUid());
                    break;
                // 根据证件获取居民码
                case "getCodeByCard":
                    bodyParams = getCodeByCardBody(queryBody.getCardType(), queryBody.getCardNo());
                    break;
                // 解析二维码
                case "parsingCode":
                    bodyParams = parsingCodeBody(queryBody.getQrCode());
                    break;
                // 获取用户信息
                case "getUserInfo":
                    bodyParams = getUserInfoBody(queryBody.getJmmCode());
                    break;
                default:
                    return R.fail("参数无效");
            }
            String message = "";
            // 0：明文 1：加密
            if (isSecret.equals("1")) {
                message = DzsCodeSign.makeSign(appSecret, bodyParams.toJSONString());
            } else {
                message = bodyParams.toJSONString();
            }
            Map<String, Object> headerMap = headerParams(message);
            // 0：明文 1：加密
            JSONObject requestBody = new JSONObject();
            requestBody.put("message", message);
            SslUtils.ignoreSsl();
            JSONObject resultObj = httpService.post(url + "/" + queryBody.getInterfaceName(), headerMap, requestBody);
            log.info("居民码{}接口响应：{}", queryBody.getInterfaceName(), resultObj);
            if (!resultObj.containsKey("code") || !resultObj.getString("code").equals("200")) {
                if (resultObj.containsKey("msg") && !StringUtils.isBlank(resultObj.getString("msg"))) {
                    return R.fail(resultObj.getString("msg"));
                }
                return R.fail("接口异常");
            }
            if (resultObj.containsKey("data")) {
                return R.ok(resultObj.getJSONObject("data"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
        return R.ok();
    }

    @ApiOperation(value = "多码互认接口")
    @PostMapping("/mutualDiscern")
    public R<?> mutualDiscern(@RequestBody DzsCodeBody body) {
        // 请求参数示例：
        // {
        //    "qrCode":"SDQR0000001A00010001371400011667058654613299203000169828216216982822221410ff8de0b234bdf8a92932e36173578789c4099bf3606c4c1e3e175a91a5ac754434bd767e4155ffdf095dc8a096714d4b86e535231efbb5383e9fd4cd13f2"
        // }
        if(body == null || StringUtils.isBlank(body.getQrCode())) {
            return R.fail("请求参数无效");
        }
        try {
            JSONObject bodyParams = mutualDiscernBody(body.getQrCode());
            Map<String, Object> headerMap;
            SslUtils.ignoreSsl();
            String message = "";
            JSONObject resultObj;
            // 0：明文 1：加密
            if (isSecret.equals("1")) {
                message = DzsCodeSign.makeSign(appSecret, bodyParams.toJSONString());
                headerMap = headerParams(message);
                resultObj = httpService.post(mutualUrl + "/mutualDiscern", headerMap, message);
            } else {
                headerMap = headerParams(bodyParams.toJSONString());
                resultObj = httpService.post(mutualUrl + "/mutualDiscern", headerMap, bodyParams);
            }
            log.info("居民码多码互认接口响应：{}", resultObj);
            if (!resultObj.containsKey("code") || !resultObj.getString("code").equals("200")) {
                if (resultObj.containsKey("msg") && !StringUtils.isBlank(resultObj.getString("msg"))) {
                    if (resultObj.containsKey("detail") && !StringUtils.isBlank(resultObj.getString("detail"))) {
                        return R.fail(resultObj.getString("msg") + "->" + resultObj.getString("detail"));
                    } else {
                        return R.fail(resultObj.getString("msg"));
                    }
                }
                return R.fail("接口异常");
            }
            if (resultObj.containsKey("data")) {
                return R.ok(resultObj.getJSONObject("data"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
        return R.ok();
    }

    /**
     * 设置请求header参数 参数都是必填的
     */
    private Map<String, Object> headerParams(String message) {
        Map<String, Object> headMap = new HashMap<>();
        // 客户端生成的安全随机码
        String nonceStr = DzsCodeSign.getRandomString(10);
        // 当前时间（yyyyMMddHHmmss）
        String time = DateUtils.formatDate(new Date(), "yyyyMMddHHmmss");
        // 根据appid、nonceStr、time和(message)，经过HMAC算法计算的值
        String str = appid + "&" + time + "&" + nonceStr;
        if (isWhole.equals("1")) {
            str += message;
        }
        System.out.println("签名字符串：" + str);

        // 应用ID
        headMap.put("appid", appid);
        headMap.put("nonceStr", nonceStr);
        headMap.put("time", time);
        headMap.put("sign", DzsCodeSign.makeSign(appSecret, str));
        headMap.put("isSecret", isSecret);
        headMap.put("isWhole", isWhole);
        return headMap;
    }

    /**
     * 设置body参数 - 判断是否已注册居民码
     */
    private JSONObject isRegBody(String cardType, String cardNo) {
        JSONObject jsonObject = new JSONObject();
        // 证件类型 必
        jsonObject.put("cardType", cardType);
        // 证件编号 必
        jsonObject.put("cardNo", cardNo);
        return jsonObject;
    }

    /**
     * 设置body参数 - 用户注册
     */
    private JSONObject registerBody(DzsCodeBody body) {
        JSONObject jsonObject = new JSONObject();
        return jsonObject;
    }

    /**
     * 设置body参数 - 根据UID获取居民码
     */
    private JSONObject getCodeByUidBody(String uid) {
        JSONObject jsonObject = new JSONObject();
        // 居民码UID 必
        jsonObject.put("uid", uid);
        // 经度
        jsonObject.put("longitude", "");
        // 纬度
        jsonObject.put("latitude", "");
        // 县区编码
        jsonObject.put("county", "");
        // 街道
        jsonObject.put("subdistrict", "");
        // 地点
        jsonObject.put("position", "");
        return jsonObject;
    }

    /**
     * 设置body参数 - 根据证件获取居民码
     */
    private JSONObject getCodeByCardBody(String cardType, String cardNo) {
        JSONObject jsonObject = new JSONObject();
        // 证件类型 必
        jsonObject.put("cardType", cardType);
        // 证件编号 必
        jsonObject.put("cardNo", cardNo);
        // 经度
        jsonObject.put("longitude", "");
        // 纬度
        jsonObject.put("latitude", "");
        // 县区编码
        jsonObject.put("county", "");
        // 街道
        jsonObject.put("subdistrict", "");
        // 地点
        jsonObject.put("position", "");
        return jsonObject;
    }

    /**
     * 设置body参数 - 解析二维码
     */
    private JSONObject parsingCodeBody(String qrCode) {
        JSONObject jsonObject = new JSONObject();
        // 必
        jsonObject.put("QrCode", qrCode);
        // 机构编码 必
        jsonObject.put("institutionCode", institutionCode);
        // 终端类型（0人工、1自助）必
        jsonObject.put("channelCode", "0");
        // 业务环节 必
        jsonObject.put("businessStepCode", businessStepCode);
        // 用码时间 yyyy-MM-dd HH:mm:ss 必
        jsonObject.put("useTime", DateUtils.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
        // 返回值类型（对接时添加，后台的 二维码解析返回值类型）必
        jsonObject.put("returnValueType", "01");
        // 经度
        jsonObject.put("longitude", "");
        // 纬度
        jsonObject.put("latitude", "");
        // 县区编码
        jsonObject.put("county", "");
        // 街道
        jsonObject.put("subdistrict", "");
        // 地点
        jsonObject.put("position", "");
        return jsonObject;
    }

    /**
     * 设置body参数 - 获取用户信息
     */
    private JSONObject getUserInfoBody(String jmmCode) {
        JSONObject jsonObject = new JSONObject();
        // 省居民码授权码 必
        jsonObject.put("jmmCode", jmmCode);
        return jsonObject;
    }

    /**
     * 设置body参数 - 多码互认 二维码识读
     */
    private JSONObject mutualDiscernBody(String qrCode) {
        JSONObject jsonObject = new JSONObject();
        // 必
        jsonObject.put("QrCode", qrCode);
        // 城市编码 必
        jsonObject.put("useCityCode", useCityCode);
        // 机构编码 必
        jsonObject.put("institutionCode", institutionCode);
        // 终端类型（0人工、1自助）必
        jsonObject.put("channelCode", "0");
        // 业务环节（接口方提供） 必
        jsonObject.put("businessStepCode", businessStepCode);
        // 用卡时间 yyyy-MM-dd HH:mm:ss 必
        jsonObject.put("useTime", DateUtils.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
        // 返回值类型（对接时添加，后台的 二维码解析返回值类型）必
        jsonObject.put("returnValueType", "01");
        // 经度
        jsonObject.put("longitude", "");
        // 纬度
        jsonObject.put("latitude", "");
        // 县区编码 （市辖区：371401 德城区：371402 陵城区：371403 宁津县：371422 庆云县：371423 临邑县：371424 齐河县：371425 平原县：371426 夏津县：371427 武城县：371428 乐陵市：371481 禹城市：371482 天衢新区：371471）
        jsonObject.put("county", "");
        // 街道
        jsonObject.put("subdistrict", "");
        // 地点
        jsonObject.put("position", "");
        return jsonObject;
    }

}
