package com.kym.miniapp.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import com.kym.common.utils.HttpUtil;
import com.kym.entity.ParkingCouponRecord;
import com.kym.entity.User;
import com.kym.entity.WashOrder;
import com.kym.service.MpMsgTemplateService;
import com.kym.service.ParkingCouponRecordService;
import com.kym.service.UserService;
import com.kym.service.WashOrderService;
import com.kym.service.cache.KymCache;
import com.kym.common.R;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.UUID;

/**
 * 停车优惠链接跳转
 * @author skyline
 * @since 2024-08-07
 */
@Slf4j
@RestController
@RequestMapping("/parking-coupon")
public class ParkingCouponController {

    private static final int MAX_REDIRECT_URL_LENGTH = 2000;

    private final WashOrderService washOrderService;
    private final MpMsgTemplateService mpMsgTemplateService;
    private final UserService userService;
    private final ParkingCouponRecordService parkingCouponRecordService;

    @Value("${kym.domain}")
    private String DOMAIN;

    public ParkingCouponController(WashOrderService washOrderService,
                                   MpMsgTemplateService mpMsgTemplateService,
                                   UserService userService,
                                   ParkingCouponRecordService parkingCouponRecordService) {
        this.washOrderService = washOrderService;
        this.mpMsgTemplateService = mpMsgTemplateService;
        this.userService = userService;
        this.parkingCouponRecordService = parkingCouponRecordService;
    }

    /**
     * 停车优惠链接跳转
     */
    @SaIgnore
    @GetMapping
    public void jump(HttpServletResponse response, @RequestParam String code) throws IOException {
        log.info("停车券跳转请求, code: {}", code);
        var url = KymCache.INSTANCE.getParkingCouponUrl(code);
        log.info("从缓存获取停车券URL, code: {}, urlLength: {}", code, url != null ? url.length() : 0);
        if (url == null || url.isEmpty()) {
            log.warn("停车券链接已失效, code: {}", code);
            response.setContentType("text/html; charset=utf-8");
            response.getWriter().write("""
                <!DOCTYPE html>
                <html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
                <title>链接已失效</title>
                <style>body{font-family:sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#f5f5f5}
                .card{background:#fff;padding:32px 24px;border-radius:8px;text-align:center;box-shadow:0 2px 12px rgba(0,0,0,.08)}
                h2{color:#e74c3c;margin:0 0 8px}p{color:#666;margin:0}</style>
                </head><body><div class="card"><h2>链接已失效</h2><p>停车优惠券链接已过期或不存在，请联系客服</p></div></body></html>""");
            return;
        }

        parkingCouponRecordService.lambdaUpdate()
                .eq(ParkingCouponRecord::getCode, code)
                .set(ParkingCouponRecord::getStatus, ParkingCouponRecord.STATUS_已使用)
                .set(ParkingCouponRecord::getUsedTime, LocalDateTime.now())
                .update();

        if (url.length() < MAX_REDIRECT_URL_LENGTH) {
            log.info("短 URL 直接重定向, code: {}, urlLength: {}", code, url.length());
            response.sendRedirect(url);
            return;
        }

        // URL 过长时使用服务端代理，避免浏览器 GET 请求触发第三方服务器 414
        log.info("长 URL 使用代理, code: {}, urlLength: {}", code, url.length());
        try {
            String content = HttpUtil.get(url);
            String origin = extractOrigin(url);
            content = content.replaceAll("(?i)<head([^>]*)>", "<head$1><base href=\"" + origin + "\">");
            response.setContentType("text/html; charset=utf-8");
            response.getWriter().write(content);
        } catch (Exception e) {
            log.error("代理停车券页面失败, url: {}", url, e);
            response.setContentType("text/html; charset=utf-8");
            response.getWriter().write("""
                <!DOCTYPE html>
                <html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
                <title>服务暂不可用</title>
                <style>body{font-family:sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#f5f5f5}
                .card{background:#fff;padding:32px 24px;border-radius:8px;text-align:center;box-shadow:0 2px 12px rgba(0,0,0,.08)}
                h2{color:#e67e22;margin:0 0 8px}p{color:#666;margin:0}</style>
                </head><body><div class="card"><h2>服务暂不可用</h2><p>停车优惠页面暂时无法访问，请稍后重试或联系客服</p></div></body></html>""");
        }
    }

    /**
     * 查询是否符合停车优惠
     */
    @SaIgnore
    @GetMapping("/checkParkingCoupon")
    public R<String> checkParkingCoupon(@RequestParam String mobilePhone) {
        return R.success(washOrderService.checkParkingCoupon(mobilePhone));
    }

    /**
     * [测试] 生成停车券短链接，返回 url 可直接在浏览器打开测试
     */
    @SaIgnore
    @GetMapping("/testLink")
    public R<String> testLink(@RequestParam String mobilePhone) {
        return R.success(washOrderService.checkParkingCoupon(mobilePhone));
    }

    /**
     * [测试] 发送停车券微信模板消息，需要用户已关注公众号且有 mpOpenid
     */
    @SaIgnore
    @GetMapping("/testSend")
    public String testSend(@RequestParam String mobilePhone) {
        var user = userService.lambdaQuery().eq(User::getMobilePhone, mobilePhone).one();
        if (user == null) {
            return "用户不存在: " + mobilePhone;
        }
        var orders = washOrderService.lambdaQuery()
                .eq(WashOrder::getUserId, user.getId())
                .eq(WashOrder::getPayStatus, WashOrder.PAY_STATUS_已支付)
                .orderByDesc(WashOrder::getId)
                .list();
        if (orders.isEmpty()) {
            return "该用户没有已支付订单，无法构造模板消息参数";
        }
        var washOrder = orders.get(0);
        var parkingCouponUrl = KymCache.INSTANCE.getParkingQrCodeUrlByStationId(washOrder.getStationId());
        var code = UUID.randomUUID().toString();
        KymCache.INSTANCE.setParkingCouponCode(code, parkingCouponUrl, 3600 * 2L);
        var url = DOMAIN + "/api/parking-coupon?code=" + code;
        mpMsgTemplateService.sendParkingCouponMsg(washOrder, url);
        return "已发送, url=" + url;
    }

    private static String extractOrigin(String url) {
        try {
            URL u = new URL(url);
            int port = u.getPort();
            return u.getProtocol() + "://" + u.getHost() + (port > 0 ? ":" + port : "") + "/";
        } catch (Exception e) {
            return url;
        }
    }

}
