package shop.alien.store.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import shop.alien.entity.result.R;
import shop.alien.entity.store.LifeUser;
import shop.alien.entity.store.StoreAliPayLog;
import shop.alien.store.service.AliService;
import shop.alien.store.service.LifeUserService;
import shop.alien.store.util.ali.AliApi;
import shop.alien.store.util.ali.AliSms;
import shop.alien.store.util.ali.SmsSendLimitException;
import shop.alien.util.ali.AliOSSUtil;
import shop.alien.util.common.AlipayTradeAppPay;
import shop.alien.util.common.AlipayTradeRefund;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

/**
 * @author ssk
 * @version 1.0
 * @date 2024/12/11 17:34
 */
@Slf4j
@Api(tags = {"二期-阿里接口"})
@ApiSort(9)
@CrossOrigin
@RestController
@RequestMapping("/ali")
@RequiredArgsConstructor
public class AliController {

    private final AliApi aliPayConfig;

    private final AliSms aliSmsConfig;

    private final AliService aliService;

    private final AlipayTradeRefund alipayTradeRefund;

    private final AliOSSUtil aliOSSUtil;

    private final AliApi aliApi;

    private final LifeUserService lifeUserService;

    @ApiOperation("阿里回调")
    @ApiOperationSupport(order = 1)
    @GetMapping("/notify")
    public void notify(HttpServletRequest request, HttpServletResponse response) {
        log.info("AliController.notify");
        aliService.notify(request);
    }

    @ApiOperation("证件二要素核验（身份证走阿里核验，护照等非身份证证件跳过核验）")
    @ApiOperationSupport(order = 2)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "姓名", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "idCard", value = "证件号（身份证号或护照号等）", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "appType", value = "端区分(0:用户, 1:商家)", dataType = "Integer", paramType = "query", required = true, defaultValue = "0")
    })
    @GetMapping("/getIdInfo")
    public R getIdInfo(@RequestParam("name") String name, @RequestParam("idCard") String idCard, @RequestParam("appType") Integer appType) {
        String normalizedName = name == null ? null : name.trim();
        String normalizedIdCard = idCard == null ? null : idCard.trim().toUpperCase();
        log.info("AliController.getIdInfo?name={}&idCard={}", normalizedName, normalizedIdCard);
        if (appType == 0) {
            // 根据证件号查询未注销用户：同一证件只能实名一个账号
            int size = lifeUserService.count(new LambdaQueryWrapper<LifeUser>()
                    .eq(LifeUser::getIdCard, normalizedIdCard)
                    .eq(LifeUser::getLogoutFlag, 0));
            if (size > 0) {
                return R.fail("该证件已实名认证过");
            }
        }
        if (!isChineseIdCard(normalizedIdCard)) {
            log.info("AliController.getIdInfo 非中国大陆身份证，跳过二要素核验 idCard={}", normalizedIdCard);
            return R.success("身份验证成功");
        }
        if (aliPayConfig.getIdInfo(normalizedName, normalizedIdCard)) {
            return R.success("身份验证成功");
        }
//        Map map = new HashMap();
//        map.put("msg","身份验证失败");
//        return R.data(map,"身份验证失败");
        return R.fail("身份证号码与姓名不一致，请检查后重新填写");
    }

    /** 是否为中国大陆居民身份证号（18位或15位） */
    private static boolean isChineseIdCard(String idCard) {
        if (idCard == null || idCard.isEmpty()) {
            return false;
        }
        return idCard.matches("^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dX]$")
                || idCard.matches("^\\d{15}$");
    }

    @ApiOperation("单笔转账接口")
    @ApiOperationSupport(order = 3)
    @ApiImplicitParams({@ApiImplicitParam(name = "name", value = "收款人姓名", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "idCard", value = "收款人身份证号", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "phone", value = "收款人手机号", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "money", value = "收款金额", dataType = "String", paramType = "query", required = true)})
    @GetMapping("/pay")
    public R pay(String name, String idCard, String phone, String money) {
        log.info("AliController.pay?name={}&idCard={}&phone={}&money={}", name, idCard, phone, money);
        StoreAliPayLog pay = aliPayConfig.pay(name, idCard, phone, money);
        if (null != pay) {
            return R.data(pay);
        }
        return R.fail("转账失败");
    }

    @ApiOperation("发送短信")
    @ApiOperationSupport(order = 4)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "appType", value = "端区分(0:用户, 1:商家, 2:商家web端)", dataType = "Integer", paramType = "query", required = true, defaultValue = "0"),
            @ApiImplicitParam(name = "businessType", value = "业务类型 (0:登录, 1:修改密码, 2:注册, 3:修改手机号, 4:注销店铺, 5:注销账号, 6:忘记密码)", dataType = "Integer", paramType = "query", required = true, defaultValue = "0")
    })
    @GetMapping("/sendSms")
    public R sendSms(
            @RequestParam("phone") String phone,
            @RequestParam("appType") Integer appType,
            @RequestParam("businessType") Integer businessType
    ) {
        try {
            Integer code = aliSmsConfig.sendSms(phone, appType, businessType);
            log.info("AliController.sendSms?phone={}&code={}&businessType={}", phone, code, businessType);
            if (code != null) {
                return R.data("短信发送成功");
            }
            return R.fail("短信发送失败");
        } catch (SmsSendLimitException e) {
            log.warn("AliController.sendSms limit exceeded, phone={}, businessType={}", phone, businessType);
            return R.fail(e.getMessage());
        }
    }



    @ApiOperation("发送律师账号密码短信")
    @ApiOperationSupport(order = 5)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "userName", value = "用户名", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "password", value = "密码", dataType = "String", paramType = "query", required = true)
    })
    @GetMapping("/sendLawyerSms")
    public R sendLawyerSms(
            @RequestParam("phone") String phone,
            @RequestParam("userName") String userName,
            @RequestParam("password") String password
    ) {
        Integer result = aliSmsConfig.sendLawyerSms(phone, userName, password);
        log.info("AliController.sendLawyerSms?phone={}&userName={}&result={}", phone, userName, result);
        if (result != null) {
            return R.data("短信发送成功");
        }
        return R.fail("短信发送失败");
    }

    @ApiOperation("校验短信验证码")
    @ApiOperationSupport(order = 4)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "appType", value = "端区分(0:用户, 1:商家, 2:商家web端)", dataType = "Integer", paramType = "query", required = true, defaultValue = "0"),
            @ApiImplicitParam(name = "businessType", value = "业务类型 (0:登录, 1:修改密码, 2:注册, 3:修改手机号, 4:注销店铺, 5:注销账号, 6:忘记密码)", dataType = "Integer", paramType = "query", required = true, defaultValue = "0"),
            @ApiImplicitParam(name = "code", value = "验证码", dataType = "Integer", paramType = "query", required = true)
    })
    @GetMapping("/checkSmsCode")
    public R checkSmsCode(
            @RequestParam("phone") String phone,
            @RequestParam("appType") Integer appType,
            @RequestParam("businessType") Integer businessType,
            @RequestParam("code") Integer code
    ) {
        log.info("AliController.checkSmsCode?phone={}&appType={}&businessType={}&code={}", phone, appType, businessType, code);
        if (aliSmsConfig.checkSmsCode(phone, appType, businessType, code)) {
            return R.success("验证码校验成功");
        }
        return R.fail("验证码校验失败");
    }

    @ApiOperation("银行卡核验")
    @ApiOperationSupport(order = 5)
    @ApiImplicitParams({@ApiImplicitParam(name = "name", value = "姓名", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "idCard", value = "身份证号", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "bankCard", value = "银行卡号", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "query", required = true)
    })
    @GetMapping("/validateBankCardInfo")
    public R validateBankCardInfo(String name, String idCard, String bankCard, String phone) {
        log.info("AliController.getBankCardInfo?name={}&idCard={}&bankCard={}&phone={}", name, idCard, bankCard, phone);
        if (aliPayConfig.validateBankCardInfo(name, idCard, bankCard, phone)) {
            return R.success("银行卡信息验证成功");
        }
        return R.fail("银行卡信息验证失败");
    }

    @ApiOperation("H5人脸核身初始化")
    @ApiOperationSupport(order = 6)
    @ApiImplicitParams({@ApiImplicitParam(name = "name", value = "姓名", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "idCard", value = "身份证号", dataType = "String", paramType = "query", required = true)})
    @GetMapping("/h5FaceInit")
    public R h5FaceInit(String name, String idCard) {
        log.info("AliController.h5FaceInit?name={}&idCard={}", name, idCard);
        JSONObject jsonObject = aliPayConfig.h5FaceInit(name, idCard);
        if (null != jsonObject) {
            return R.data(jsonObject);
        }
        return R.fail("H5人脸核身初始化失败");
    }

    @ApiOperation("H5人脸核身结果查询")
    @ApiOperationSupport(order = 7)
    @ApiImplicitParams({@ApiImplicitParam(name = "certifyId", value = "认证单据号", dataType = "String", paramType = "query", required = true)})
    @GetMapping("/h5FaceResult")
    public R h5FaceResult(String certifyId) {
        log.info("AliController.h5FaceResult?certifyId={}", certifyId);
        JSONObject jsonObject = aliPayConfig.h5FaceResult(certifyId);
        if (null != jsonObject) {
            return R.data(jsonObject);
        }
        return R.fail("H5人脸核身初始化失败");
    }

    @ApiOperation("跳转支付宝人脸核身初始化")
    @ApiOperationSupport(order = 8)
    @ApiImplicitParams({@ApiImplicitParam(name = "name", value = "姓名", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "idCard", value = "身份证号", dataType = "String", paramType = "query", required = true)})
    @GetMapping("/jumpToAliPayInit")
    public R jumpToAliPayInit(String name, String idCard) {
        log.info("AliController.jumpToAliPayInit?name={}&idCard={}", name, idCard);
        JSONObject jsonObject = aliPayConfig.jumpToAliPayInit(name, idCard);
        if (null != jsonObject) {
            return R.data(jsonObject);
        }
        return R.fail("跳转支付宝人脸核身初始化失败");
    }

    @ApiOperation("跳转支付宝人脸核身开始认证")
    @ApiOperationSupport(order = 9)
    @ApiImplicitParams({@ApiImplicitParam(name = "certifyId", value = "认证ID", dataType = "String", paramType = "query", required = true)})
    @GetMapping("/jumpToAliPay")
    public R jumpToAliPay(String certifyId) {
        log.info("AliController.jumpToAliPay?certifyId={}", certifyId);
        JSONObject jsonObject = aliPayConfig.jumpToAliPay(certifyId);
        if (null != jsonObject) {
            return R.data(jsonObject);
        }
        return R.fail("跳转支付宝人脸核身开始认证失败");
    }

    @ApiOperation("跳转支付宝人脸核身查询记录")
    @ApiOperationSupport(order = 10)
    @ApiImplicitParams({@ApiImplicitParam(name = "certifyId", value = "认证ID", dataType = "String", paramType = "query", required = true)})
    @GetMapping("/jumpToAliPayResult")
    public R jumpToAliPayResult(String certifyId) {
        log.info("AliController.jumpToAliPayResult?certifyId={}", certifyId);
        JSONObject jsonObject = aliPayConfig.jumpToAliPayResult(certifyId);
        if (null != jsonObject) {
            return R.data(jsonObject);
        }
        return R.fail("跳转支付宝人脸核身查询记录失败");
    }

    @GetMapping("/userPay")
    public String userPay() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        return AlipayTradeAppPay.executeAlipayPayment(dateFormat.format(new Date()), "0.01", "测试支付");
    }

    @GetMapping("/returnPay")
    public void returnPay(String orderNo, String refundAmount) {
        alipayTradeRefund.processRefund(orderNo, refundAmount, "退款");
    }

    @ApiOperation("跳转支付宝人脸核身查询记录")
    @ApiOperationSupport(order = 11)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "文件", dataType = "File", paramType = "query", required = true),
            @ApiImplicitParam(name = "ossFilePath", value = "oss中的文件路径", dataType = "String", paramType = "query", required = true)
    })
    @GetMapping("/uploadFile")
    public R<String> uploadFile(@RequestParam(value = "file") MultipartFile multipartFile, @RequestParam(value = "ossFilePath") String ossFilePath) {
        return R.data(aliOSSUtil.uploadFile(multipartFile, ossFilePath));
    }

    @ApiOperation("支付")
    @ApiOperationSupport(order = 12)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "price", value = "金额", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "subject", value = "类目", dataType = "String", paramType = "query", required = true)
    })
    @GetMapping("/zhifu")
    public R<JSONObject> zhifu(@RequestParam(value = "price") String price, @RequestParam(value = "subject") String subject) {
        return R.data(aliApi.promotionPackagePay(price, subject));
    }

    @ApiOperation("处理退款")
    @ApiOperationSupport(order = 13)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "outTradeNo", value = "订单编号", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "refundAmount", value = "退款金额", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "refundReason", value = "退款原因", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "partialRefundCode", value = "部分退款编号", dataType = "String", paramType = "query")
    })
    @GetMapping("/processRefund")
    public String processRefund(@RequestParam("outTradeNo") String outTradeNo,
                                @RequestParam("refundAmount") String refundAmount,
                                @RequestParam("refundReason") String refundReason,
                                @RequestParam(value = "partialRefundCode", required = false) String partialRefundCode) {
        log.info("AliController.processRefund?outTradeNo={}, refundAmount={}, refundReason={}, partialRefundCode={}",
                outTradeNo, refundAmount, refundReason, partialRefundCode);
        return aliApi.processRefund(outTradeNo, refundAmount, refundReason, partialRefundCode);
    }

    /**
     * 支付宝OCR识别
     *
     * @param imageId 图片id
     * @param ocrType OCR识别类型
     * @return OCR识别结果
     * @throws Exception 识别异常
     */
    @ApiOperation("支付宝OCR识别方式一")
    @ApiOperationSupport(order = 14)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "imageId", value = "图片id", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "ocrType", value = "OCR识别类型", dataType = "String", paramType = "query", required = true)
    })
    @GetMapping("/ocrRequest")
    public R<JSONObject> ocrRequest(@RequestParam(value = "imageId") String imageId, @RequestParam(value = "ocrType") String ocrType) {
        try {
            return aliApi.ocrRequest(imageId, ocrType);
        } catch (Exception e) {
            return R.fail("OCR识别异常:"+e.getMessage());
        }
    }

    /**
     * 二手委托人识别（底层调用IDcard识别）
     */
    @ApiOperation("二手委托人识别（底层调用IDcard识别）")
    @ApiOperationSupport(order = 16)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "imageUrl", value = "图片文件", dataType = "File", paramType = "query", required = true),
            @ApiImplicitParam(name = "ocrType", value = "OCR识别类型", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "userName", value = "委托人姓名", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "idCard", value = "委托人身份证号", dataType = "String", paramType = "query", required = true)
    })
    @PostMapping("/secondClient")
    public R secondClient(@RequestBody Map<String, String> params)
    {
        try {
            return aliApi.secondClient(params.get("imageUrl"), params.get("ocrType"), params.get("userName"), params.get("idCard"));
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }
    }

    /**
     * 支付宝OCR识别
     *
     * @return OCR识别结果
     * @throws Exception 识别异常
     */
    @ApiOperation("支付宝OCR识别方式二")
    @ApiOperationSupport(order = 15)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ocrType", value = "OCR识别类型", dataType = "String", paramType = "query", required = true)
    })
    @PostMapping("/ocrRequestByBase64")
    public R ocrRequestByBase64(MultipartFile imageFile,
                                @RequestParam("ocrType") String ocrType) {
        try {
            return aliApi.ocrRequestByBase64(imageFile, ocrType);
        } catch (Exception e) {
            return R.fail("OCR识别异常:"+e.getMessage());
        }
    }
    /**
     * 调用OCR识别接口
     */
    @ApiOperation("调用OCR识别接口")
    @ApiOperationSupport(order = 17)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "imageUrls", value = "图片文件", dataType = "File", paramType = "query", required = true),
            @ApiImplicitParam(name = "ocrType", value = "OCR识别类型", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "storeId", value = "店铺ID", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(name = "userId", value = "用户ID", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(name = "storeUserId", value = "店铺用户ID", dataType = "String", paramType = "query", required = false)
    })
    @PostMapping("/ocrRequestUrl")
    public R ocrRequestUrl(@RequestBody Map<String, String> params) {
        try {
            return aliApi.ocrRequestParams(params);
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }
    }
}