package com.gxwebsoft.common.core.controller;

import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.gxwebsoft.common.core.dto.qr.*;
import com.gxwebsoft.common.core.utils.EncryptedQrCodeUtil;
import com.gxwebsoft.common.core.utils.QrCodeDecryptResult;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.awt.*;
import java.io.IOException;
import java.util.Base64;
import java.util.Map;

/**
 * 二维码生成控制器
 *
 * @author WebSoft
 * @since 2025-08-18
 */
@RestController
@RequestMapping("/api/qr-code")
@Tag(name = "二维码生成API")
@Validated
public class QrCodeController extends BaseController {

    @Autowired
    private EncryptedQrCodeUtil encryptedQrCodeUtil;

    @Operation(summary = "生成普通二维码")
    @GetMapping("/create-qr-code")
    public void createQrCode(
            @Parameter(description = "要编码的数据") @RequestParam("data") String data,
            @Parameter(description = "二维码尺寸，格式：宽x高 或 单个数字") @RequestParam(value = "size", defaultValue = "200x200") String size,
            HttpServletResponse response) throws IOException {

        try {
            // 解析尺寸
            String[] dimensions = size.split("x");
            int width = Integer.parseInt(dimensions[0]);
            int height = dimensions.length > 1 ? Integer.parseInt(dimensions[1]) : width;

            // 验证尺寸范围，防止过大的图片
            if (width < 50 || width > 1000 || height < 50 || height > 1000) {
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                response.getWriter().write("尺寸必须在50-1000像素之间");
                return;
            }

            // 配置二维码
            QrConfig config = new QrConfig(width, height);
            config.setMargin(1);
            config.setForeColor(Color.BLACK);
            config.setBackColor(Color.WHITE);

            // 设置响应头
            response.setContentType("image/png");
            response.setHeader("Cache-Control", "no-cache");
            response.setHeader("Content-Disposition", "inline; filename=qrcode.png");

            // 生成二维码并直接输出到响应流
            QrCodeUtil.generate(data, config, "png", response.getOutputStream());

        } catch (NumberFormatException e) {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            response.getWriter().write("尺寸格式错误，请使用如：200x200 的格式");
        } catch (Exception e) {
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            response.getWriter().write("生成二维码失败：" + e.getMessage());
        }
    }

    @Operation(summary = "生成加密二维码")
    @PostMapping("/create-encrypted-qr-code")
    public ApiResult<?> createEncryptedQrCode(@Valid @RequestBody CreateEncryptedQrCodeRequest request) {

        try {
            // 生成加密二维码
            Map<String, Object> result = encryptedQrCodeUtil.generateEncryptedQrCode(
                    request.getData(),
                    request.getWidth(),
                    request.getHeight(),
                    request.getExpireMinutes(),
                    request.getBusinessType());

            return success("生成加密二维码成功", result);

        } catch (Exception e) {
            return fail("生成加密二维码失败：" + e.getMessage());
        }
    }

    @Operation(summary = "生成加密二维码图片流")
    @GetMapping("/create-encrypted-qr-image")
    public void createEncryptedQrImage(
            @Parameter(description = "要加密的数据") @RequestParam("data") String data,
            @Parameter(description = "二维码尺寸") @RequestParam(value = "size", defaultValue = "200x200") String size,
            @Parameter(description = "过期时间（分钟）") @RequestParam(value = "expireMinutes", defaultValue = "30") Long expireMinutes,
            @Parameter(description = "业务类型（可选）") @RequestParam(value = "businessType", required = false) String businessType,
            HttpServletResponse response) throws IOException {

        try {
            // 解析尺寸
            String[] dimensions = size.split("x");
            int width = Integer.parseInt(dimensions[0]);
            int height = dimensions.length > 1 ? Integer.parseInt(dimensions[1]) : width;

            // 验证尺寸范围
            if (width < 50 || width > 1000 || height < 50 || height > 1000) {
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                response.getWriter().write("尺寸必须在50-1000像素之间");
                return;
            }

            // 验证过期时间
            if (expireMinutes <= 0 || expireMinutes > 1440) {
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                response.getWriter().write("过期时间必须在1-1440分钟之间");
                return;
            }

            // 生成加密二维码
            Map<String, Object> result = encryptedQrCodeUtil.generateEncryptedQrCode(data, width, height, expireMinutes, businessType);
            String base64Image = (String) result.get("qrCodeBase64");

            // 解码Base64图片
            byte[] imageBytes = Base64.getDecoder().decode(base64Image);

            // 设置响应头
            response.setContentType("image/png");
            response.setHeader("Cache-Control", "no-cache");
            response.setHeader("Content-Disposition", "inline; filename=encrypted_qrcode.png");
            response.setHeader("X-QR-Token", (String) result.get("token"));
            response.setHeader("X-QR-Expire-Minutes", result.get("expireMinutes").toString());

            // 输出图片
            response.getOutputStream().write(imageBytes);

        } catch (NumberFormatException e) {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            response.getWriter().write("尺寸格式错误，请使用如：200x200 的格式");
        } catch (Exception e) {
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            response.getWriter().write("生成加密二维码失败：" + e.getMessage());
        }
    }

    @Operation(summary = "解密二维码数据")
    @PostMapping("/decrypt-qr-data")
    public ApiResult<?> decryptQrData(@Valid @RequestBody DecryptQrDataRequest request) {

        try {
            String decryptedData = encryptedQrCodeUtil.decryptData(request.getToken(), request.getEncryptedData());
            return success("解密成功", decryptedData);

        } catch (Exception e) {
            return fail("解密失败：" + e.getMessage());
        }
    }

    @Operation(summary = "验证并解密二维码内容（自包含模式）")
    @PostMapping("/verify-and-decrypt-qr")
    public ApiResult<?> verifyAndDecryptQr(@Valid @RequestBody VerifyQrContentRequest request) {

        try {
            String originalData = encryptedQrCodeUtil.verifyAndDecryptQrCode(request.getQrContent());
            return success("验证和解密成功", originalData);

        } catch (Exception e) {
            return fail("验证和解密失败：" + e.getMessage());
        }
    }

    @Operation(summary = "验证并解密二维码内容（返回完整结果，包含业务类型）")
    @PostMapping("/verify-and-decrypt-qr-with-type")
    public ApiResult<QrCodeDecryptResult> verifyAndDecryptQrWithType(@Valid @RequestBody VerifyQrContentRequest request) {

        try {
            QrCodeDecryptResult result = encryptedQrCodeUtil.verifyAndDecryptQrCodeWithResult(request.getQrContent());
            return success("验证和解密成功", result);

        } catch (Exception e) {
            return fail("验证和解密失败：" + e.getMessage(),null);
        }
    }

    @Operation(summary = "生成业务加密二维码（门店核销模式）")
    @PostMapping("/create-business-encrypted-qr-code")
    public ApiResult<?> createBusinessEncryptedQrCode(@Valid @RequestBody CreateBusinessEncryptedQrCodeRequest request) {

        try {
            // 生成业务加密二维码
            Map<String, Object> result = encryptedQrCodeUtil.generateBusinessEncryptedQrCode(
                    request.getData(),
                    request.getWidth(),
                    request.getHeight(),
                    request.getBusinessKey(),
                    request.getExpireMinutes(),
                    request.getBusinessType());

            return success("生成业务加密二维码成功", result);

        } catch (Exception e) {
            return fail("生成业务加密二维码失败：" + e.getMessage());
        }
    }

    @Operation(summary = "门店核销二维码（业务模式）")
    @PostMapping("/verify-business-qr")
    public ApiResult<?> verifyBusinessQr(@Valid @RequestBody VerifyBusinessQrRequest request) {

        try {
            String originalData = encryptedQrCodeUtil.verifyAndDecryptQrCodeWithBusinessKey(
                    request.getQrContent(), request.getBusinessKey());
            return success("核销成功", originalData);

        } catch (Exception e) {
            return fail("核销失败：" + e.getMessage());
        }
    }

    @Operation(summary = "检查token是否有效")
    @GetMapping("/check-token")
    public ApiResult<?> checkToken(
            @Parameter(description = "要检查的token") @RequestParam("token") String token) {

        try {
            boolean isValid = encryptedQrCodeUtil.isTokenValid(token);
            return success("检查完成", isValid);

        } catch (Exception e) {
            return fail("检查token失败：" + e.getMessage());
        }
    }

    @Operation(summary = "使token失效")
    @PostMapping("/invalidate-token")
    public ApiResult<?> invalidateToken(@Valid @RequestBody InvalidateTokenRequest request) {

        try {
            encryptedQrCodeUtil.invalidateToken(request.getToken());
            return success("token已失效");

        } catch (Exception e) {
            return fail("使token失效失败：" + e.getMessage());
        }
    }
}
