package com.ruoyi.database.controller;

import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUserByPhone;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.database.domain.*;
import com.ruoyi.database.domain.vo.ParkingBillInfoVO;
import com.ruoyi.database.enums.PayType;
import com.ruoyi.database.service.*;
import com.ruoyi.database.util.LicensePlateValidator;
import com.ruoyi.framework.web.service.TokenService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

@Api(tags = "小程序接口")
@RestController
@RequiredArgsConstructor
@RequestMapping("/SmallProgram")
public class SmallProgramController extends BaseController {

    private final ParkingBillInfoService parkingBillInfoService;
    private final AlipayService alipayService;
    private final BaseCustomerInfoService baseCustomerInfoService;
    private final WechatMiniProgramPayService wechatMiniProgramPayService;
    private final ParkingBillPaymentInfoService parkingBillPaymentInfoService;
    private final CustomerPlateNoInfoService customerPlateNoInfoService;
    private final TokenService tokenService;



    @GetMapping("/getOrder")
    @ApiOperation("根据车牌号查询缴费订单")
    @Transactional
    public AjaxResult getOrder(String plateNo) {
        ParkingBillInfo one = parkingBillInfoService.saveOrUpdateParkingBillInfo(plateNo);
//        ParkingBillInfo one = parkingBillInfoService.lambdaQuery()
//                .eq(ParkingBillInfo::getPlateNo, plateNo)
//                .orderByDesc(ParkingBillInfo::getCreateTime)
//                .last("limit 1")
//                .one();

        if (one == null) {
            return AjaxResult.error("未查询到停车记录");
        }else {
            ParkingBillInfoVO parkingBillInfoVO = new ParkingBillInfoVO();
            BeanUtils.copyProperties(one, parkingBillInfoVO);
            parkingBillInfoVO.setTotalCostYuan(one.getTotalCostYuan().toString() + "元");
            parkingBillInfoVO.setPayMoneyYuan(one.getPayMoneyYuan().toString() + "元");
            parkingBillInfoVO.setDeductMoneyYuan(one.getDeductMoneyYuan().toString() + "元");
            return AjaxResult.success(parkingBillInfoVO);
        }
    }



    @GetMapping("/getHistoryPlateNo")
    @ApiOperation("历史缴费车牌列表")
    public AjaxResult getHistoryOrder(HttpServletRequest request){
        LoginUserByPhone loginUserByPhone = tokenService.getLoginUserByPhone(request);
        if (loginUserByPhone == null) {
            return AjaxResult.error("用户未登录");
        }
        String phone = loginUserByPhone.getPhone();
        List<ParkingBillPaymentInfo> list = parkingBillPaymentInfoService.lambdaQuery()
                .eq(ParkingBillPaymentInfo::getPhone, phone)
                .eq(ParkingBillPaymentInfo::getPayStatus, 1)
                .list();
        Map<String, List<ParkingBillPaymentInfo>> groupedByPlateNo = list.stream()
                .collect(Collectors.groupingBy(
                        ParkingBillPaymentInfo::getPlateNo,  // 按车牌分组
                        Collectors.toList()                   // 收集为List
                ));
        ArrayList<Map<String, String>> maps = new ArrayList<>();
        for (String plateNo : groupedByPlateNo.keySet()) {
            List<ParkingBillPaymentInfo> list1 = groupedByPlateNo.get(plateNo);
            ParkingBillPaymentInfo parkingBillPaymentInfo = list1.get(0);
            Map<String, String> map = new HashMap<>();
            map.put("plateNo", plateNo);
            map.put("plateColor",parkingBillPaymentInfo.getPlateColorCn());
            maps.add(map);
        }
        return AjaxResult.success(maps);
    }



    @GetMapping("/getHistoryNoPayOrder")
    @ApiOperation("查询历史未缴费订单")
    public AjaxResult getHistoryNoPayOrder(HttpServletRequest request){
        LoginUserByPhone loginUserByPhone = tokenService.getLoginUserByPhone(request);
        if (loginUserByPhone == null) {
            return AjaxResult.error("用户未登录");
        }
        List<CustomerPlateNoInfo> list = customerPlateNoInfoService.lambdaQuery()
                .eq(CustomerPlateNoInfo::getPhone, loginUserByPhone.getPhone())
                .list();
        List<String> collect = list.stream().map(CustomerPlateNoInfo::getPlateNo).collect(Collectors.toList());
        if (collect.isEmpty()){
            return AjaxResult.success(collect);
        }
        List<ParkingBillInfo> list1 = parkingBillInfoService.lambdaQuery()
                .in(ParkingBillInfo::getPlateNo, collect)
                .eq(ParkingBillInfo::getIsPay, 0)
                .list();
        List<ParkingBillInfoVO> parkingBillInfoVOS = new ArrayList<>();
        list1.forEach(b -> {
            ParkingBillInfoVO parkingBillInfoVO = new ParkingBillInfoVO();
            BeanUtils.copyProperties(b, parkingBillInfoVO);
            parkingBillInfoVO.setTotalCostYuan(b.getTotalCostYuan().toString() + "元");
            parkingBillInfoVO.setPayMoneyYuan(b.getPayMoneyYuan().toString() + "元");
            parkingBillInfoVO.setDeductMoneyYuan(b.getDeductMoneyYuan().toString() + "元");
            parkingBillInfoVOS.add(parkingBillInfoVO);
        });
        return AjaxResult.success(parkingBillInfoVOS);
    }




    @GetMapping("/getBindTheVehicle")
    @ApiOperation("查询已绑定车辆")
    public AjaxResult getBindTheVehicle(HttpServletRequest request){
        LoginUserByPhone loginUserByPhone = tokenService.getLoginUserByPhone(request);
        if (loginUserByPhone == null) {
            return AjaxResult.error("用户未登录");
        }
        List<CustomerPlateNoInfo> list = customerPlateNoInfoService.lambdaQuery()
                .eq(CustomerPlateNoInfo::getPhone, loginUserByPhone.getPhone())
                .list();
        return AjaxResult.success(list);
    }



    @PostMapping("/bindTheVehicle")
    @ApiOperation("绑定车辆")
    public AjaxResult bindTheVehicle(@RequestBody BindTheVehicle bindTheVehicle,HttpServletRequest request){
        LoginUserByPhone loginUserByPhone = tokenService.getLoginUserByPhone(request);
        String plateNo = bindTheVehicle.getPlateNo();
        if (plateNo == null || "".equals(plateNo)) {
            return AjaxResult.error("绑定的车牌不能为空");
        }else{
            boolean valid = LicensePlateValidator.isValid(plateNo);
            if (!valid) {
                return AjaxResult.error("绑定的车牌格式不正确");
            }
        }
        List<CustomerPlateNoInfo> list = customerPlateNoInfoService.lambdaQuery()
                .eq(CustomerPlateNoInfo::getPlateNo, plateNo)
                .list();
        if (list != null && list.size() > 0) {
            return AjaxResult.error("车牌已被绑定");
        }
        CustomerPlateNoInfo customerPlateNoInfo = new CustomerPlateNoInfo();
        customerPlateNoInfo.setPlateNo(plateNo);
        customerPlateNoInfo.setPlateType(bindTheVehicle.getPlateType());
        customerPlateNoInfo.setPhone(loginUserByPhone.getPhone());
        return toAjax(customerPlateNoInfoService.saveOrUpdate(customerPlateNoInfo));
    }



    @PostMapping("/payFees")
    @ApiOperation("缴费")
    @Transactional
    public AjaxResult payFees(@RequestBody PayFees payFees,HttpServletRequest request){
        LoginUserByPhone loginUserByPhone = tokenService.getLoginUserByPhone(request);

        ParkingBillInfo one = parkingBillInfoService.lambdaQuery()
                .eq(ParkingBillInfo::getBillCode, payFees.getBillCode())
                .last("limit 1")
                .one();
        if (one == null) {
            return AjaxResult.error("停车记录查询失败");
        }
        ParkingBillInfo parkingBillInfo = parkingBillInfoService.saveOrUpdateParkingBillInfo(one.getPlateNo());
        if (parkingBillInfo != null) {
            one = parkingBillInfo;
        }
        String generate = generate(loginUserByPhone.getPhone());
        BaseCustomerInfo one1 = baseCustomerInfoService.lambdaQuery()
                .eq(BaseCustomerInfo::getPhone, loginUserByPhone.getPhone())
                .last("limit 1")
                .one();
        if (one1 == null) {
            return AjaxResult.error("用户信息出错");
        }
        String openId = null;
        PayType payType = PayType.getByCode(payFees.getPayType());
        switch (payType) {
            case WECHAT:
                openId = one1.getOpenId();
                break;
            case ALIPAY:
                openId = one1.getAlipayUserId();
                break;
        }
        String clientIp = wechatMiniProgramPayService.getClientIpAddress(request);
        Map<String, Object> order = createOrder(payFees, generate, openId, one, clientIp);

        ParkingBillPaymentInfo parkingBillPaymentInfo = new ParkingBillPaymentInfo();
        parkingBillPaymentInfo.setBillCode(one.getBillCode());
        parkingBillPaymentInfo.setPlateNo(one.getPlateNo());
        parkingBillPaymentInfo.setPlateColor(one.getPlateColor());
        parkingBillPaymentInfo.setOpenId(openId);
        parkingBillPaymentInfo.setPayType(payFees.getPayType());
        parkingBillPaymentInfo.setPhone(loginUserByPhone.getPhone());
        parkingBillPaymentInfo.setPayStatus(0);
        parkingBillPaymentInfo.setOrderId(generate);
        boolean b = parkingBillPaymentInfoService.saveOrUpdate(parkingBillPaymentInfo);
        if (b) {
            return AjaxResult.success(order);
        }else {
            return AjaxResult.error("创建订单出错");
        }


    }



    /**
     * 创建支付宝 微信 订单
     * @param payFees
     * @param orderId
     * @param openId
     * @param parkingBillInfo
     * @param clientIp
     * @return
     */
    private Map<String, Object> createOrder(PayFees payFees,
                                            String orderId,
                                            String openId,
                                            ParkingBillInfo parkingBillInfo,
                                            String clientIp) {
        PayType payType = PayType.getByCode(payFees.getPayType());

        switch (payType) {
            case WECHAT:
                return wechatMiniProgramPayService.createJsapiOrder(
                        openId,orderId,parkingBillInfo.getPayMoney(),
                        "常客隆智慧停车缴费",clientIp);
            case ALIPAY:
                return alipayService.createOrder(orderId,
                        parkingBillInfo.getPayMoneyYuan().toString(),
                        "常客隆智慧停车缴费",openId);

            default:
                throw new IllegalArgumentException("不支持的登录方式: " + payType);
        }
    }




    public static String generate(String phone) {
        // 1. 参数校验
        if (phone == null || phone.length() < 4) {
            throw new IllegalArgumentException("Invalid phone number");
        }
        // 2. 获取手机尾号（后4位更常见）
        String phoneSuffix = phone.substring(phone.length() - 4);
        // 3. 使用更精确的时间戳
        String timePart = Instant.now().toEpochMilli() + "";  // 毫秒时间戳
        // 4. 增加更多随机性
        int random = ThreadLocalRandom.current().nextInt(1000, 9999);
        return phoneSuffix + timePart.substring(timePart.length() - 10) + random;
    }
}
