package com.gameplatform.server.controller.link;

import com.gameplatform.server.mapper.agent.LinkBatchMapper;
import com.gameplatform.server.mapper.agent.LinkTaskMapper;
import com.gameplatform.server.model.dto.link.GameInterfaceResponse;

import com.gameplatform.server.model.entity.agent.LinkBatch;
import com.gameplatform.server.model.entity.agent.LinkTask;
import com.gameplatform.server.service.external.ScriptClient;
import com.gameplatform.server.service.admin.SystemConfigService;
import com.gameplatform.server.service.link.LinkStatusService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.CacheControl;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import reactor.core.publisher.Mono;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/api/link")
@Tag(name = "图片代理", description = "转发脚本端的图片，避免混合内容")
public class QrProxyController {
    private static final Logger log = LoggerFactory.getLogger(QrProxyController.class);
    
    private final ScriptClient scriptClient;
    private final LinkStatusService linkStatusService;
    private final String appBaseUrl;
    private final LinkTaskMapper linkTaskMapper;
    private final LinkBatchMapper linkBatchMapper;
    private final SystemConfigService systemConfigService;

    public QrProxyController(ScriptClient scriptClient, 
                           LinkStatusService linkStatusService,
                           @Value("${app.base-url}") String appBaseUrl,
                           LinkTaskMapper linkTaskMapper,
                           LinkBatchMapper linkBatchMapper,
                           SystemConfigService systemConfigService) {
        this.scriptClient = scriptClient;
        this.linkStatusService = linkStatusService;
        this.appBaseUrl = appBaseUrl;
        this.linkTaskMapper = linkTaskMapper;
        this.linkBatchMapper = linkBatchMapper;
        this.systemConfigService = systemConfigService;
    }

    @GetMapping(value = "/image/{codeNo}/qr.png", produces = MediaType.IMAGE_PNG_VALUE)
    @Operation(summary = "二维码图片代理")
    public Mono<ResponseEntity<byte[]>> qr(@PathVariable("codeNo") String codeNo) {
        // 通过codeNo查询machineId
        String machineId = linkStatusService.getMechainIdByCode(codeNo);
        if (machineId == null) {
            log.warn("无法找到codeNo对应的machineId");
            return createNotFoundResponseMono();
        }

        String path = "/" + machineId + "/二维码.png";
        return scriptClient.getQrPng(path)
                .map(bytes -> ResponseEntity.ok()
                        .contentType(MediaType.IMAGE_PNG)
                        .cacheControl(CacheControl.maxAge(30, TimeUnit.SECONDS).cachePublic())
                        .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=qr.png")
                        .body(bytes))
                .onErrorResume(WebClientResponseException.NotFound.class, ex -> {
                    log.warn("图片不存在");
                    return createNotFoundResponseMono();
                })
                .onErrorResume(WebClientResponseException.class, ex -> {
                    log.warn("获取图片失败: status={}, error={}", ex.getStatusCode(), ex.getMessage());
                    return Mono.just(ResponseEntity.status(ex.getStatusCode()).build());
                });
    }

    @GetMapping(value = "/image/{codeNo}/homepage.png", produces = MediaType.IMAGE_PNG_VALUE)
    @Operation(summary = "首次主页图片代理")
    public Mono<ResponseEntity<byte[]>> homepage(@PathVariable("codeNo") String codeNo) {
        return linkStatusService.getLinkStatus(codeNo)
                .flatMap(linkStatus -> {
                    String machineId = linkStatus.getMachineId();
                    if (machineId == null) {
                        log.warn("无法找到codeNo对应的machineId");
                        return createNotFoundResponseMono();
                    }

                    String path = "/" + machineId + "/首次主页.png";
                    return scriptClient.getImagePng(path)
                            .map(bytes -> ResponseEntity.ok()
                                    .contentType(MediaType.IMAGE_PNG)
                                    .cacheControl(CacheControl.maxAge(30, TimeUnit.SECONDS).cachePublic())
                                    .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=homepage.png")
                                    .body(bytes))
                            .onErrorResume(WebClientResponseException.NotFound.class, ex -> {
                                log.warn("图片不存在");
                                return createNotFoundResponseMono();
                            })
                            .onErrorResume(WebClientResponseException.class, ex -> {
                                log.warn("获取图片失败: status={}, error={}", ex.getStatusCode(), ex.getMessage());
                                return Mono.just(ResponseEntity.status(ex.getStatusCode()).build());
                            });
                })
                .onErrorResume(Exception.class, ex -> {
                    log.error("获取链接状态失败: {}", ex.getMessage());
                    return createInternalServerErrorResponseMono();
                });
    }

    @GetMapping(value = "/image/{codeNo}/first-reward.png", produces = MediaType.IMAGE_PNG_VALUE)
    @Operation(summary = "首次赏金图片代理")
    public Mono<ResponseEntity<byte[]>> firstReward(@PathVariable("codeNo") String codeNo) {
        return linkStatusService.getLinkStatus(codeNo)
                .flatMap(linkStatus -> {
                    String machineId = linkStatus.getMachineId();
                    if (machineId == null) {
                        log.warn("无法找到codeNo对应的machineId");
                        return createNotFoundResponseMono();
                    }

                    String path = "/" + machineId + "/首次赏金.png";
                    return scriptClient.getImagePng(path)
                            .map(bytes -> ResponseEntity.ok()
                                    .contentType(MediaType.IMAGE_PNG)
                                    .cacheControl(CacheControl.maxAge(30, TimeUnit.SECONDS).cachePublic())
                                    .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=first-reward.png")
                                    .body(bytes))
                            .onErrorResume(WebClientResponseException.NotFound.class, ex -> {
                                log.warn("图片不存在");
                                return createNotFoundResponseMono();
                            })
                            .onErrorResume(WebClientResponseException.class, ex -> {
                                log.warn("获取图片失败: status={}, error={}", ex.getStatusCode(), ex.getMessage());
                                return Mono.just(ResponseEntity.status(ex.getStatusCode()).build());
                            });
                })
                .onErrorResume(Exception.class, ex -> {
                    log.error("获取链接状态失败: {}", ex.getMessage());
                    return createInternalServerErrorResponseMono();
                });
    }

    @GetMapping(value = "/image/{codeNo}/mid-reward.png", produces = MediaType.IMAGE_PNG_VALUE)
    @Operation(summary = "中途赏金图片代理")
    public Mono<ResponseEntity<byte[]>> midReward(@PathVariable("codeNo") String codeNo) {
        return linkStatusService.getLinkStatus(codeNo)
                .flatMap(linkStatus -> {
                    String machineId = linkStatus.getMachineId();
                    if (machineId == null) {
                        log.warn("无法找到codeNo对应的machineId");
                        return createNotFoundResponseMono();
                    }

                    String path = "/" + machineId + "/中途赏金.png";
                    return scriptClient.getImagePng(path)
                            .map(bytes -> ResponseEntity.ok()
                                    .contentType(MediaType.IMAGE_PNG)
                                    .cacheControl(CacheControl.maxAge(30, TimeUnit.SECONDS).cachePublic())
                                    .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=mid-reward.png")
                                    .body(bytes))
                            .onErrorResume(WebClientResponseException.NotFound.class, ex -> {
                                log.warn("图片不存在");
                                return createNotFoundResponseMono();
                            })
                            .onErrorResume(WebClientResponseException.class, ex -> {
                                log.warn("获取图片失败: status={}, error={}", ex.getStatusCode(), ex.getMessage());
                                return Mono.just(ResponseEntity.status(ex.getStatusCode()).build());
                            });
                })
                .onErrorResume(Exception.class, ex -> {
                    log.error("获取链接状态失败: {}", ex.getMessage());
                    return createInternalServerErrorResponseMono();
                });
    }

    @GetMapping(value = "/image/{codeNo}/end-reward.png", produces = MediaType.IMAGE_PNG_VALUE)
    @Operation(summary = "结束赏金图片代理")
    public Mono<ResponseEntity<byte[]>> endReward(@PathVariable("codeNo") String codeNo) {
        return linkStatusService.getLinkStatus(codeNo)
                .flatMap(linkStatus -> {
                    String machineId = linkStatus.getMachineId();
                    if (machineId == null) {
                        log.warn("无法找到codeNo对应的machineId: {}", codeNo);
                        return createNotFoundResponseMono();
                    }

                    String path = "/" + machineId + "/结束赏金.png";
                    return scriptClient.getImagePng(path)
                            .map(bytes -> ResponseEntity.ok()
                                    .contentType(MediaType.IMAGE_PNG)
                                    .cacheControl(CacheControl.maxAge(30, TimeUnit.SECONDS).cachePublic())
                                    .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=end-reward.png")
                                    .body(bytes))
                            .onErrorResume(WebClientResponseException.NotFound.class, ex -> {
                                log.warn("图片不存在: path={}", path);
                                return createNotFoundResponseMono();
                            })
                            .onErrorResume(WebClientResponseException.class, ex -> {
                                log.warn("获取图片失败: path={}, status={}, error={}", path, ex.getStatusCode(), ex.getMessage());
                                return Mono.just(ResponseEntity.status(ex.getStatusCode()).build());
                            });
                })
                .onErrorResume(Exception.class, ex -> {
                    log.error("获取链接状态失败: codeNo={}, error={}", codeNo, ex.getMessage());
                    return createInternalServerErrorResponseMono();
                });
    }

    @GetMapping("/{codeNo}/images")
    @Operation(summary = "获取所有图片代理链接")
    public ResponseEntity<Map<String, String>> getImageLinks(@PathVariable("codeNo") String codeNo) {
        Map<String, String> imageLinks = new HashMap<>();
        
        // 添加二维码链接
        imageLinks.put("qrCode", appBaseUrl + "/api/link/image/" + codeNo + "/qr.png");
        
        // 添加其他图片链接
        imageLinks.put("homepage", appBaseUrl + "/api/link/image/" + codeNo + "/homepage.png");
        imageLinks.put("firstReward", appBaseUrl + "/api/link/image/" + codeNo + "/first-reward.png");
        imageLinks.put("midReward", appBaseUrl + "/api/link/image/" + codeNo + "/mid-reward.png");
        imageLinks.put("endReward", appBaseUrl + "/api/link/image/" + codeNo + "/end-reward.png");
        
        return ResponseEntity.ok()
                .cacheControl(CacheControl.maxAge(5, TimeUnit.MINUTES).cachePublic())
                .body(imageLinks);
    }

    @GetMapping("/{codeNo}/game-interface")
    @Operation(summary = "获取游戏界面数据", description = "返回四张图片链接和总点数信息")
    public ResponseEntity<GameInterfaceResponse> getGameInterface(@PathVariable("codeNo") String codeNo) {
        log.info("获取游戏界面数据: codeNo={}", codeNo);
        
        try {
            // 查询链接任务
            LinkTask linkTask = linkTaskMapper.findByCodeNo(codeNo);
            if (linkTask == null) {
                log.warn("链接任务不存在: codeNo={}", codeNo);
                return ResponseEntity.notFound().build();
            }
            
            // 查询批次信息
            LinkBatch linkBatch = linkBatchMapper.findById(linkTask.getBatchId());
            if (linkBatch == null) {
                log.warn("批次信息不存在: batchId={}", linkTask.getBatchId());
                return ResponseEntity.notFound().build();
            }
            
            // 构建响应对象
            GameInterfaceResponse response = new GameInterfaceResponse();
            response.setCodeNo(codeNo);
            response.setMachineId(linkTask.getMachineId());
            response.setQuantity(linkBatch.getQuantity());
            response.setTimes(linkBatch.getTimes());
            response.setTotalPoints(linkBatch.getQuantity() * linkBatch.getTimes());
            response.setCompletedPoints(linkTask.getCompletedPoints());
            // 设置游戏区域信息
            response.setRegion(linkTask.getRegion());
            response.setRegionDesc(getRegionDescription(linkTask.getRegion()));
            
            // 设置图片链接
            response.setQrCodeUrl(appBaseUrl + "/api/link/image/" + codeNo + "/qr.png");
            response.setHomepageUrl(appBaseUrl + "/api/link/image/" + codeNo + "/homepage.png");
            response.setFirstRewardUrl(appBaseUrl + "/api/link/image/" + codeNo + "/first-reward.png");
            response.setMidRewardUrl(appBaseUrl + "/api/link/image/" + codeNo + "/mid-reward.png");
            response.setEndRewardUrl(appBaseUrl + "/api/link/image/" + codeNo + "/end-reward.png");
            // 设置用户进度显示格式（从系统配置读取）
            response.setProgressDisplayFormat(systemConfigService.getProgressDisplayFormat());
            
            log.info("游戏界面数据构建完成: codeNo={}, totalPoints={}", codeNo, response.getTotalPoints());
            
            return ResponseEntity.ok()
                    .cacheControl(CacheControl.maxAge(2, TimeUnit.MINUTES).cachePublic())
                    .body(response);
                    
        } catch (Exception e) {
            log.error("获取游戏界面数据失败: codeNo={}, error={}", codeNo, e.getMessage(), e);
            return ResponseEntity.internalServerError().build();
        }
    }
    
    /**
     * 获取区域描述
     */
    private String getRegionDescription(String region) {
        if (region == null) {
            return "未选择区域";
        }
        switch (region) {
            case "Q":
                return "QQ区";
            case "V":
                return "微信区";
            default:
                return "未知区域";
        }
    }
    
    /**
     * 创建404响应的Mono包装
     * @return Mono<ResponseEntity<byte[]>>
     */
    private Mono<ResponseEntity<byte[]>> createNotFoundResponseMono() {
        return Mono.just(ResponseEntity.notFound().build());
    }
    
    /**
     * 创建500响应的Mono包装
     * @return Mono<ResponseEntity<byte[]>>
     */
    private Mono<ResponseEntity<byte[]>> createInternalServerErrorResponseMono() {
        return Mono.just(ResponseEntity.internalServerError().build());
    }
}

