package server.logic.ws_protocol.JSON.handlers.channels;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import server.logic.ws_protocol.JSON.ConnectionContext;
import server.logic.ws_protocol.JSON.entyties.Net_Request;
import server.logic.ws_protocol.JSON.entyties.Net_Response;
import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler;
import server.logic.ws_protocol.JSON.handlers.channels.entyties.Net_ListGroupChats200_Request;
import server.logic.ws_protocol.JSON.handlers.channels.entyties.Net_ListGroupChats200_Response;
import server.logic.ws_protocol.JSON.utils.NetExceptionResponseFactory;
import server.logic.ws_protocol.WireCodes;
import shine.db.SqliteDbController;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class Net_ListGroupChats200_Handler implements JsonMessageHandler {
    private static final Logger log = LoggerFactory.getLogger(Net_ListGroupChats200_Handler.class);

    @Override
    public Net_Response handle(Net_Request baseRequest, ConnectionContext ctx) {
        Net_ListGroupChats200_Request req = (Net_ListGroupChats200_Request) baseRequest;
        if (req.getLogin() == null || req.getLogin().isBlank()) {
            return NetExceptionResponseFactory.error(req, WireCodes.Status.BAD_REQUEST, "bad_fields", "Некорректные поля: login");
        }
        try (Connection c = SqliteDbController.getInstance().getConnection()) {
            String canonicalLogin = ChannelsReadSupport.canonicalLogin(c, req.getLogin().trim());
            if (canonicalLogin == null) {
                return NetExceptionResponseFactory.error(req, 404, "user_not_found", "Пользователь не найден");
            }
            Net_ListGroupChats200_Response resp = new Net_ListGroupChats200_Response();
            resp.setOp(req.getOp());
            resp.setRequestId(req.getRequestId());
            resp.setStatus(WireCodes.Status.OK);
            resp.setLogin(canonicalLogin);
            resp.setChats(loadRows(c, canonicalLogin));
            return resp;
        } catch (Exception e) {
            log.error("ListGroupChats200 failed", e);
            return NetExceptionResponseFactory.error(req, WireCodes.Status.INTERNAL_ERROR, "internal_error", "Внутренняя ошибка сервера");
        }
    }

    private List<Net_ListGroupChats200_Response.Row> loadRows(Connection c, String login) throws Exception {
        String sql = """
            SELECT s.owner_login, s.owner_bch_name, s.channel_root_block_number, s.channel_root_block_hash,
                   s.channel_name, s.chat_title, s.updated_at_ms,
                   COALESCE(m.members_count, 0) AS members_count
            FROM chat200_state s
            LEFT JOIN (
                SELECT owner_bch_name, channel_root_block_number, COUNT(*) AS members_count
                FROM chat200_members_state
                WHERE is_active = 1
                GROUP BY owner_bch_name, channel_root_block_number
            ) m
            ON m.owner_bch_name = s.owner_bch_name
            AND m.channel_root_block_number = s.channel_root_block_number
            WHERE s.owner_login = ? COLLATE NOCASE
            ORDER BY s.updated_at_ms DESC, s.channel_root_block_number DESC
            """;
        List<Net_ListGroupChats200_Response.Row> out = new ArrayList<>();
        try (PreparedStatement ps = c.prepareStatement(sql)) {
            ps.setString(1, login);
            try (ResultSet rs = ps.executeQuery()) {
                while (rs.next()) {
                    Net_ListGroupChats200_Response.Row row = new Net_ListGroupChats200_Response.Row();
                    row.setOwnerLogin(rs.getString("owner_login"));
                    row.setOwnerBlockchainName(rs.getString("owner_bch_name"));
                    row.setChannelRootBlockNumber(rs.getInt("channel_root_block_number"));
                    row.setChannelRootBlockHash(ChannelsReadSupport.toHex(rs.getBytes("channel_root_block_hash")));
                    row.setChannelName(rs.getString("channel_name"));
                    row.setChatTitle(rs.getString("chat_title"));
                    row.setUpdatedAtMs(rs.getLong("updated_at_ms"));
                    row.setMembersCount(rs.getInt("members_count"));
                    out.add(row);
                }
            }
        }
        return out;
    }
}

