package com.erp.gateway.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * API网关统计控制器
 */
@Slf4j
@RestController
@RequestMapping("/api/gateway/stats")
public class GatewayStatsController {

    private final ReactiveStringRedisTemplate redisTemplate;

    public GatewayStatsController(ReactiveStringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 获取API调用统计（按天）
     */
    @GetMapping("/daily")
    public Mono<Map<String, Object>> getDailyStats(@RequestParam(defaultValue = "7") Integer days) {
        String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        String key = "gateway:api:day:" + today;

        return redisTemplate.opsForZSet().range(key, 0, -1)
                .collectList()
                .map(items -> {
                    Map<String, Object> result = new LinkedHashMap<>();
                    result.put("date", today);
                    result.put("totalCalls", getScoreFromZSet(items, "total"));
                    return result;
                });
    }

    /**
     * 获取租户API调用排行
     */
    @GetMapping("/tenants")
    public Mono<Map<String, Object>> getTenantStats(
            @RequestParam(required = false) String startDate,
            @RequestParam(required = false) String endDate) {
        if (startDate == null) {
            startDate = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        }
        if (endDate == null) {
            endDate = startDate;
        }

        String key = "gateway:api:tenant:*:" + startDate;

        return redisTemplate.keys(key)
                .flatMap(k -> redisTemplate.opsForZSet().range(k, 0, -1).collectList().map(items -> {
                    // 从key中提取tenantId
                    String tenantId = k.replace("gateway:api:tenant:", "").replace(":" + startDate, "");
                    Map<String, Object> stats = new LinkedHashMap<>();
                    stats.put("tenantId", tenantId);
                    stats.put("count", getScoreFromZSet(items, "count"));
                    stats.put("errors", getScoreFromZSet(items, "errors"));
                    return stats;
                }))
                .collectList()
                .map(list -> {
                    // 按count降序排序
                    list.sort((a, b) -> Long.compare(
                            (Long) ((Map<String, Object>) b).getOrDefault("count", 0L),
                            (Long) ((Map<String, Object>) a).getOrDefault("count", 0L)
                    ));
                    Map<String, Object> result = new LinkedHashMap<>();
                    result.put("date", startDate);
                    result.put("ranking", list);
                    return result;
                });
    }

    /**
     * 获取端点调用统计
     */
    @GetMapping("/endpoints")
    public Mono<Map<String, Object>> getEndpointStats(
            @RequestParam(required = false) String path,
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "20") Integer pageSize) {
        String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        String pattern = "gateway:api:endpoint:*:" + today;

        return redisTemplate.keys(pattern)
                .flatMap(k -> redisTemplate.opsForZSet().range(k, 0, -1).collectList().map(items -> {
                    String endpoint = k.replace("gateway:api:endpoint:", "").replace(":" + today, "");
                    Map<String, Object> stats = new LinkedHashMap<>();
                    stats.put("path", endpoint);
                    stats.put("count", getScoreFromZSet(items, "count"));
                    stats.put("errors", getScoreFromZSet(items, "errors"));
                    return stats;
                }))
                .collectList()
                .map(list -> {
                    list.sort((a, b) -> Long.compare(
                            (Long) ((Map<String, Object>) b).getOrDefault("count", 0L),
                            (Long) ((Map<String, Object>) a).getOrDefault("count", 0L)
                    ));
                    int start = (page - 1) * pageSize;
                    int end = Math.min(start + pageSize, list.size());
                    List<Map<String, Object>> pageData = start < list.size() ? list.subList(start, end) : List.of();
                    Map<String, Object> result = new LinkedHashMap<>();
                    result.put("date", today);
                    result.put("total", list.size());
                    result.put("page", page);
                    result.put("pageSize", pageSize);
                    result.put("data", pageData);
                    return result;
                });
    }

    /**
     * 获取实时统计（最近1小时）
     */
    @GetMapping("/realtime")
    public Mono<Map<String, Object>> getRealtimeStats() {
        String currentHour = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HH"));
        String key = "gateway:api:hour:" + currentHour;

        return redisTemplate.opsForZSet().range(key, 0, -1).collectList()
                .map(items -> {
                    Map<String, Object> result = new LinkedHashMap<>();
                    result.put("hour", currentHour);
                    result.put("totalCalls", getScoreFromZSet(items, "total"));
                    return result;
                });
    }

    /**
     * 获取最近的API请求日志
     */
    @GetMapping("/logs")
    public Mono<Map<String, Object>> getRequestLogs(
            @RequestParam(required = false) String path,
            @RequestParam(required = false) Integer status,
            @RequestParam(defaultValue = "50") Integer limit) {
        String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        String key = "gateway:api:requests:" + today;

        return redisTemplate.opsForList().range(key, -limit, -1)
                .collectList()
                .map(items -> {
                    List<Map<String, Object>> logs = new ArrayList<>();
                    for (String item : items) {
                        try {
                            logs.add(parseLogEntry(item));
                        } catch (Exception e) {
                            // 忽略解析失败的日志
                        }
                    }

                    // 过滤
                    if (path != null) {
                        logs = logs.stream()
                                .filter(l -> path.equals(l.get("path")))
                                .toList();
                    }
                    if (status != null) {
                        logs = logs.stream()
                                .filter(l -> status.equals(l.get("status")))
                                .toList();
                    }

                    Map<String, Object> result = new LinkedHashMap<>();
                    result.put("count", logs.size());
                    result.put("logs", logs);
                    return result;
                });
    }

    private long getScoreFromZSet(List<org.springframework.data.redis.core.ReactiveZSetOperations.TypedTuple<String>> items, String key) {
        if (items == null) return 0;
        for (var item : items) {
            if (key.equals(item.getValue())) {
                return item.getScore() != null ? item.getScore().longValue() : 0;
            }
        }
        return 0;
    }

    private long getScoreFromZSet(List<String> items, String key) {
        // 占位实现，实际从TypedTuple中获取
        return 0;
    }

    private Map<String, Object> parseLogEntry(String json) {
        Map<String, Object> result = new LinkedHashMap<>();
        try {
            result.put("path", extractJsonValue(json, "path"));
            result.put("method", extractJsonValue(json, "method"));
            result.put("tenant", extractJsonValue(json, "tenant"));
            result.put("status", Integer.parseInt(extractJsonValue(json, "status")));
            result.put("duration", Long.parseLong(extractJsonValue(json, "duration")));
            result.put("time", Long.parseLong(extractJsonValue(json, "time")));
        } catch (Exception e) {
            log.warn("解析日志条目失败: {}", json);
        }
        return result;
    }

    private String extractJsonValue(String json, String key) {
        String pattern = "\"" + key + "\":";
        int start = json.indexOf(pattern) + pattern.length();
        int end = json.indexOf(",", start);
        if (end == -1) {
            end = json.indexOf("}", start);
        }
        String value = json.substring(start, end).trim();
        if (value.startsWith("\"")) {
            value = value.substring(1, value.length() - 1);
        }
        return value;
    }
}
