package com.kym.miniapp.controller;

import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson2.JSONObject;
import com.kym.common.R;
import com.kym.common.annotation.ApiLog;
import com.kym.common.config.WxConfig;
import com.kym.common.enums.WxApi;
import com.kym.common.utils.HttpUtil;
import com.kym.entity.enplus.response.EnResponse;
import com.kym.entity.miniapp.ChargeOrder;
import com.kym.entity.miniapp.queryParams.OrderQueryParams;
import com.kym.service.admin.StationService;
import com.kym.service.enplus.EnNotifyService;
import com.kym.service.enplus.EnPlusService;
import com.kym.service.miniapp.ChargeOrderService;
import com.kym.service.miniapp.ChargeService;
import lombok.SneakyThrows;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.Map;


/**
 * 充电
 *
 * @author skyline
 * @since 2023-06-27
 */
@RestController
@RequestMapping("/charge")
public class ChargerController {

    private final StationService stationService;

    private final EnPlusService enPlusService;

    private final ChargeService chargeService;

    private final ChargeOrderService chargeOrderService;

    private final EnNotifyService enNotifyService;

    private final WxConfig wxConfig;


    public ChargerController(StationService stationService, EnPlusService enPlusService, ChargeService chargeService, ChargeOrderService chargeOrderService, EnNotifyService enNotifyService, WxConfig wxConfig) {
        this.stationService = stationService;
        this.enPlusService = enPlusService;
        this.chargeService = chargeService;
        this.chargeOrderService = chargeOrderService;
        this.enNotifyService = enNotifyService;
        this.wxConfig = wxConfig;
    }

    /**
     * 充电站列表
     *
     * @param pageNum
     * @param pageSize
     * @return
     */
    @SneakyThrows
    @GetMapping("/listStation")
    R<?> listChargeStation(
            @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        return R.success(stationService.queryLocalStationInfo(pageNum, pageSize));
    }

    /**
     * 充电站状态
     *
     * @param ids
     * @return
     */
    @GetMapping("/stationStatus")
    R<?> stationStatus(@RequestParam("stationIds") String ids) {
        // 请求en+接口
        var response = stationService.stationStatus(ids.split(","));
        return R.success(response);
    }

    @GetMapping("/token")
    R<String> queryToken() {
        return R.success(enPlusService.queryToken());
    }

    @ApiLog("启动充电")
    @GetMapping("/startCharge/{connectorId}")
    R<?> startCharge(@PathVariable("connectorId") String connectorId,
                     @RequestParam(value = "userRechargeRightsId", required = false) Long userRechargeRightsId,
                     @RequestParam(value = "userCouponId", required = false) Long userCouponId,
                     @RequestParam(value = "isBooking", defaultValue = "false") Boolean isBooking,
                     @RequestParam(value = "startTime", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
                     @RequestParam(value = "endTime", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
        var userId = StpUtil.getLoginIdAsLong();
        return R.success(chargeService.queryStartCharge(userId, connectorId, userRechargeRightsId, userCouponId, isBooking, startTime, endTime));
    }

    @ApiLog("取消预约充电")
    @GetMapping("/cancelBooking")
    R<?> cancelBooking() {
        chargeService.cancelBooking();
        return R.success();
    }

    @ApiLog("修改预约充电时间")
    @GetMapping("/modifyBookingTime")
    R<?> modifyBookingTime(@RequestParam("startChargeSeq") String startChargeSeq, @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime) {
        chargeService.modifyBookingTime(startChargeSeq, startTime);
        return R.success();
    }

    @ApiLog("预约改立即充电")
    @GetMapping("immediatelyCharge/{connectorId}")
    R<?> immediatelyCharge(@PathVariable("connectorId") String connectorId) {
        return R.success(chargeService.immediatelyCharge(connectorId));
    }

    @ApiLog("停止充电")
    @GetMapping("/stopCharge/{connectorId}")
    R<?> stopCharge(@PathVariable("connectorId") String connectorId) {
        chargeService.queryStopCharge(StpUtil.getLoginIdAsLong(), connectorId);
        return R.success();
    }

    /**
     * 查询当前用户充电状态
     *
     * @return
     */
    @GetMapping("/chargeStatus")
    R<ChargeOrder> chargeStatus() {
        return R.success(chargeService.queryEquipChargeStatus());
    }

    /**
     * 查询充电策略
     *
     * @param connectorId
     * @return
     */
    @GetMapping("/businessPolicy/{connectorId}")
    R<?> businessPolicy(@PathVariable("connectorId") String connectorId) {
        return R.success(chargeService.queryEquipBusinessPolicy(connectorId));
    }

    /**
     * 用户订单列表
     *
     * @return
     */
    @GetMapping("/listUserChargeOrders")
    R<?> listUserChargeOrders(@ModelAttribute OrderQueryParams params) {
        return R.success(chargeOrderService.listUserChargeOrders(params));
    }

    /**
     * 充电订单详情
     *
     * @param startChargeSeq
     * @return
     */
    @GetMapping("/orderDetail/{startChargeSeq}")
    R<?> orderDetail(@PathVariable("startChargeSeq") String startChargeSeq) {
        return R.success(chargeOrderService.orderDetailForApp(startChargeSeq));
    }

    /**
     * 订单优惠详情
     *
     * @param startChargeSeq
     * @param discountType
     * @return
     */
    @GetMapping("/orderDiscountDetail")
    R<?> orderDiscountDetail(@RequestParam("startChargeSeq") String startChargeSeq, @RequestParam("discountType") String discountType) {
        return R.success(chargeOrderService.orderDiscountDetail(startChargeSeq, discountType));
    }

    /**
     * 图片二维码识别
     *
     * @param imgUrl
     * @return
     */
    @GetMapping("/qrCode")
    R<?> qrCode(String imgUrl) {
        var accessTokenJson = HttpUtil.getJson(WxApi.WX_GET_ACCESS_TOKEN.getApi(), Map.of("appid", wxConfig.getAppid(), "secret", wxConfig.getSecret()));
        var accessToken = accessTokenJson.getString("access_token");
        // https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/img-ocr/img/scanQRCode.html
        // 问候微信API文档撰写祖宗十八代，这里img_url也是url传参！！！
        var res = HttpUtil.post(WxApi.WX_QR_CODE.getApi().replace("ACCESS_TOKEN", accessToken).concat("&img_url=%s".formatted(imgUrl)), Map.of(), JSONObject.class);
        return R.success(res);
    }

    //====================================================以上是请求EN+接口==============================================================

    // 【我们请求en+时，数据都要加密验签；en+推送给我们的数据，需要验签解密，响应不需要加密。】

    //====================================================以下是EN+推送接口==============================================================

    /**
     * EN+场站设备状态变化推送
     *
     * @param json
     * @return 0:接收 1：丢弃/忽略，不需要重试
     */
    @PostMapping("/notification_stationStatus")
    EnResponse notificationStationStatus(@RequestBody JSONObject json) {
        return new EnResponse(enNotifyService.handleNotificationStationStatus(json));
    }

    /**
     * EN+推送启动充电结果
     *
     * @param json
     * @return StartChargeSeq SuccStat 0:成功 1：失败  FailReason 0:无 1：接收失败
     */
    @ApiLog("EN+推送启动充电结果")
    @PostMapping("/notification_start_charge_result")
    EnResponse notificationStartChargeResult(@RequestBody JSONObject json) {
        return new EnResponse(enNotifyService.handleNotificationStartChargeResult(json));
    }

    /**
     * EN+推送充电状态
     *
     * @param json
     * @return
     */
    @PostMapping("/notification_equip_charge_status")
    EnResponse notificationEquipChargeStatus(@RequestBody JSONObject json) {
        return new EnResponse(enNotifyService.handleNotificationEquipChargeStatus(json));
    }

    /**
     * EN+推送停止充电结果
     *
     * @param json
     * @return
     */
    @ApiLog("推送停止充电结果")
    @PostMapping("/notification_stop_charge_result")
    EnResponse notificationStopChargeResult(@RequestBody JSONObject json) {
        return new EnResponse(enNotifyService.handleNotificationStopChargeResult(json));
    }

    /**
     * EN+推送充电订单信息
     *
     * @param json
     * @return
     */
    @ApiLog("推送充电订单信息")
    @PostMapping("/notification_charge_order_info")
    EnResponse notificationChargeOrderInfo(@RequestBody JSONObject json) {
        return new EnResponse(enNotifyService.handleNotificationChargeOrderInfo(json));
    }


    //====================================================以下是手动同步数据接口==============================================================

    /**
     * 拉取EN+充电站信息数据并更新本地服务器数据
     *
     * @return
     */
    @GetMapping("/pullEnStations/{stationId}")
    R<?> pullEnStationInfos(@PathVariable String stationId) {
        stationService.pullEnStationInfos(stationId);
        return R.success();
    }


}
