package com.huangzj.server.web;

import com.huangzj.base.spring.module.PlayerModuleRegistry;
import com.huangzj.server.config.AppProperties;
import com.huangzj.server.event.AppDomainEvent;
import com.huangzj.server.event.DemoEventListener;
import com.huangzj.server.mongo.DemoMongoService;
import com.huangzj.server.mongo.DemoPayloadDoc;
import com.huangzj.server.redis.RedisUtil;
import java.util.LinkedHashMap;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/demo")
@RequiredArgsConstructor
public class DemoApiController {

    private final DemoMongoService demoMongoService;
    private final RedisUtil redisUtil;
    private final ApplicationEventPublisher eventPublisher;
    private final DemoEventListener demoEventListener;
    private final PlayerModuleRegistry playerModuleRegistry;
    private final AppProperties appProperties;

    @PostMapping("/mongo/save-immediate")
    public DemoPayloadDoc mongoSaveImmediate(@RequestBody DemoPayloadDoc doc) {
        return demoMongoService.saveImmediate(doc);
    }

    @PostMapping("/mongo/save-scheduled")
    public void mongoSaveScheduled(@RequestBody DemoPayloadDoc doc) {
        demoMongoService.scheduleSave(doc);
    }

    @GetMapping("/mongo/latest")
    public DemoPayloadDoc mongoLatest(@RequestParam long playerId) {
        return demoMongoService.findLatestByPlayer(playerId);
    }

    @PostMapping("/redis/set")
    public void redisSet(@RequestBody RedisKv body) {
        redisUtil.strSet(body.key(), body.value());
    }

    @GetMapping("/redis/get")
    public String redisGet(@RequestParam String key) {
        return redisUtil.strGet(key);
    }

    /** 发一个 {@link AppDomainEvent}，Listener 里会累加计数。 */
    @PostMapping("/event/publish")
    public void eventPublish(@RequestBody EventPubBody body) {
        eventPublisher.publishEvent(new AppDomainEvent(this, body.topic(), body.body()));
    }

    @GetMapping("/event/last")
    public Map<String, Object> eventLast() {
        Map<String, Object> m = new LinkedHashMap<>();
        m.put("count", demoEventListener.getReceiveCount());
        m.put("lastTopic", demoEventListener.getLastTopic());
        m.put("lastBody", demoEventListener.getLastBody());
        return m;
    }

    @GetMapping("/module/info")
    public Map<String, Object> moduleInfo() {
        Map<String, Object> m = new LinkedHashMap<>();
        m.put("playerId", appProperties.getModule().getPlayerId());
        m.put("tickIntervalMs", appProperties.getModule().getTickIntervalMs());
        m.put("modules", playerModuleRegistry.describeModules());
        return m;
    }

    @PostMapping("/module/tick")
    public String moduleTick() {
        playerModuleRegistry.runTickAll(System.currentTimeMillis());
        return "ok";
    }

    @PostMapping("/module/save")
    public void moduleSave() {
        playerModuleRegistry.saveAll();
    }

    public record RedisKv(String key, String value) {}

    public record EventPubBody(String topic, String body) {}
}
