package com.eactive.httpmockserver.api.mapper;

import com.eactive.httpmockserver.api.dto.MockHeaderDTO;
import com.eactive.httpmockserver.api.dto.MockResponseDTO;
import com.eactive.httpmockserver.api.dto.MockRouteRegisterDTO;
import com.eactive.httpmockserver.api.dto.MockRouteUpdateDTO;
import com.eactive.httpmockserver.api.entity.MockResponse;
import com.eactive.httpmockserver.api.entity.MockRoute;
import com.eactive.httpmockserver.common.mapper.CommonMapper;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import org.mapstruct.ReportingPolicy;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Mapper(componentModel = "spring",
        uses = {CommonMapper.class},
        unmappedTargetPolicy = ReportingPolicy.IGNORE)
@Component
public abstract class MockRouteMapper {

    private static final Map<String, String> XML_ESCAPE_MAP;

    static {
        XML_ESCAPE_MAP = new HashMap<>();
        XML_ESCAPE_MAP.put("&lt;", "<");
        XML_ESCAPE_MAP.put("&gt;", ">");
        XML_ESCAPE_MAP.put("&amp;", "&");
        XML_ESCAPE_MAP.put("&quot;", "\"");
        XML_ESCAPE_MAP.put("&apos;", "'");
    }

    public abstract MockRoute map(MockRouteRegisterDTO dto);
    public abstract MockRoute map(MockRouteUpdateDTO dto);


    public abstract MockRouteRegisterDTO map(MockRoute entity);

    @Mapping(target = "headers", source = "headers", qualifiedByName = "mapHeadersToMap")
    @Mapping(target = "defaultResponse", source = "defaultResponse", qualifiedByName = "mapEntityDefaultResponse")
    @Mapping(target = "body", source="body" , qualifiedByName = "unescapeBody")
    public abstract MockResponse map(MockResponseDTO dto);

    @Mapping(target = "headers", source = "headers", qualifiedByName = "mapHeadersToList")
    @Mapping(target = "defaultResponse", source = "defaultResponse", qualifiedByName = "mapDTODefaultResponse")
    @Mapping(target = "body", source="body" , qualifiedByName = "unescapeBody")
    public abstract MockResponseDTO map(MockResponse entity);

    @Named("unescapeBody")
    public static String unescapeXml(String escapedXml) {
        if (escapedXml == null || escapedXml.isEmpty()) {
            return escapedXml;
        }

        for (Map.Entry<String, String> entry : XML_ESCAPE_MAP.entrySet()) {
            escapedXml = escapedXml.replace(entry.getKey(), entry.getValue());
        }

        return escapedXml;
    }

    @Named("mapDTODefaultResponse")
    public String map(boolean value) {
        return value ? "true" : "false";
    }

    @Named("mapEntityDefaultResponse")
    public boolean map(String value) {
        if (value == null) return false;
        return value.equals("true");
    }

    @Named("mapHeadersToList")
    public List<MockHeaderDTO> mapHeadersToList(Map<String, String> headers) {
        List<MockHeaderDTO> list = new ArrayList<>();
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                MockHeaderDTO header = new MockHeaderDTO();
                header.setKey(key);
                header.setValue(value);
                list.add(header);
            }
        }
        return list;
    }


    @Named("mapHeadersToMap")
    public Map<String, String> mapHeadersToMap(List<MockHeaderDTO> headers) {
        Map<String, String> map = new HashMap<>();
        if (headers != null) {
            for (MockHeaderDTO header : headers) {
                map.put(header.getKey(), header.getValue());
            }
        }
        return map;
    }
}
