package com.eactive.httpmockserver.client.service;

import com.eactive.httpmockserver.client.dto.ApiRequestKeyValueDTO;
import com.eactive.httpmockserver.client.dto.ApiResponse;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.util.CharsetUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

public class HttpHandler extends SimpleChannelInboundHandler<FullHttpResponse> {

    private final CompletableFuture<ApiResponse> responseFuture;

    public HttpHandler(CompletableFuture<ApiResponse> responseFuture) {
        this.responseFuture = responseFuture;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpResponse response) {

        ApiResponse apiResponse = new ApiResponse();
        apiResponse.setStatus(response.status().code());
        apiResponse.setHeaders(convertHttpHeadersToList(response.headers()));
        apiResponse.setBody(response.content().toString(CharsetUtil.UTF_8));

        int headerSize = calculateHeaderSize(response.headers());
        int contentSize = response.content().readableBytes();
        int totalSize = headerSize + contentSize;
        apiResponse.setSize(totalSize);

        responseFuture.complete(apiResponse);
    }

    private int calculateHeaderSize(HttpHeaders headers) {
        int headerSize = 0;
        for (Map.Entry<String, String> entry : headers.entries()) {
            headerSize += entry.getKey().length() + entry.getValue().length() + 4; // Add 2 for ': ' and 2 for '\r\n'
        }

        // Add 2 for the final '\r\n' after the headers
        headerSize += 2;

        return headerSize;
    }

    public List<ApiRequestKeyValueDTO> convertHttpHeadersToList(HttpHeaders headers) {
        List<ApiRequestKeyValueDTO> headerList = new ArrayList<>();
        for (Map.Entry<String, String> entry : headers.entries()) {
            ApiRequestKeyValueDTO header = new ApiRequestKeyValueDTO();
            header.setKey(entry.getKey());
            header.setValue(entry.getValue());
            headerList.add(header);
        }

        return headerList;
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        responseFuture.completeExceptionally(cause);
        ctx.close();
    }
}
