package server.debug;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import server.logic.ws_protocol.JSON.debug.DebugRunLogBuffer;

import java.io.IOException;
import java.util.List;

/**
 * GET /debug/ws/logs?limit=200&runId=dbg-...
 */
public class DebugLogsServlet extends HttpServlet {

    private static final ObjectMapper MAPPER = new ObjectMapper();

    private final DebugTokenProvider tokenProvider;

    public DebugLogsServlet(DebugTokenProvider tokenProvider) {
        this.tokenProvider = tokenProvider;
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        if (!tokenProvider.isEnabled()) {
            writeError(resp, 503, "DEBUG_DISABLED", "Debug API отключен: .debug-token не найден или пуст");
            return;
        }
        if (!tokenProvider.matchesBearerHeader(req.getHeader("Authorization"))) {
            writeError(resp, 401, "UNAUTHORIZED", "Неверный Bearer token");
            return;
        }

        int limit = parseLimit(req.getParameter("limit"));
        String runId = safe(req.getParameter("runId"));

        List<DebugRunLogBuffer.Entry> list = DebugRunLogBuffer.getInstance().tail(limit, runId);

        ArrayNode rows = MAPPER.createArrayNode();
        for (DebugRunLogBuffer.Entry e : list) {
            ObjectNode row = MAPPER.createObjectNode();
            row.put("ts", e.ts);
            row.put("level", e.level);
            row.put("runId", e.runId);
            row.put("source", e.source);
            row.put("sessionId", e.sessionId);
            row.put("login", e.login);
            row.put("message", e.message);
            row.put("details", e.details);
            rows.add(row);
        }

        ObjectNode payload = MAPPER.createObjectNode();
        payload.put("count", rows.size());
        payload.put("limit", limit);
        payload.put("runIdFilter", runId);
        payload.set("logs", rows);

        writeOk(resp, payload);
    }

    private static int parseLimit(String raw) {
        try {
            int n = Integer.parseInt(String.valueOf(raw));
            if (n < 1) return 100;
            return Math.min(n, 1000);
        } catch (Exception e) {
            return 100;
        }
    }

    private static String safe(String value) {
        return value == null ? "" : value.trim();
    }

    private static void writeOk(HttpServletResponse resp, ObjectNode payload) throws IOException {
        ObjectNode root = MAPPER.createObjectNode();
        root.put("ok", true);
        root.set("payload", payload == null ? MAPPER.createObjectNode() : payload);
        writeJson(resp, 200, root);
    }

    private static void writeError(HttpServletResponse resp, int status, String code, String message) throws IOException {
        ObjectNode root = MAPPER.createObjectNode();
        root.put("ok", false);
        root.put("code", code);
        root.put("message", message);
        writeJson(resp, status, root);
    }

    private static void writeJson(HttpServletResponse resp, int status, ObjectNode root) throws IOException {
        resp.setStatus(status);
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("application/json; charset=UTF-8");
        resp.getWriter().write(MAPPER.writeValueAsString(root));
    }
}
