package at.procon.dip.ingestion.mail;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Encodes/decodes generic mail provider metadata into SourceDescriptor attributes.
 */
public final class MailProviderEnvelopeAttributes {

    public static final String KEY_PROVIDER_TYPE = "mail.providerType";
    public static final String KEY_ACCOUNT_KEY = "mail.accountKey";
    public static final String KEY_FOLDER_KEY = "mail.folderKey";
    public static final String KEY_PROVIDER_MESSAGE_KEY = "mail.providerMessageKey";
    public static final String KEY_PROVIDER_THREAD_KEY = "mail.providerThreadKey";
    public static final String KEY_PREFIX_PROVIDER_ATTRIBUTE = "mail.providerAttribute.";

    private MailProviderEnvelopeAttributes() {
    }

    public static GenericMailProviderEnvelope fromAttributes(Map<String, String> attributes) {
        if (attributes == null || attributes.isEmpty()) {
            return new GenericMailProviderEnvelope(MailProviderType.GENERIC, null, null, null, null, Map.of());
        }
        MailProviderType providerType = parseProviderType(attributes.get(KEY_PROVIDER_TYPE));
        Map<String, String> providerAttributes = new LinkedHashMap<>();
        for (Map.Entry<String, String> entry : attributes.entrySet()) {
            if (entry.getKey() != null && entry.getKey().startsWith(KEY_PREFIX_PROVIDER_ATTRIBUTE)) {
                providerAttributes.put(entry.getKey().substring(KEY_PREFIX_PROVIDER_ATTRIBUTE.length()), entry.getValue());
            }
        }
        return new GenericMailProviderEnvelope(
                providerType,
                emptyToNull(attributes.get(KEY_ACCOUNT_KEY)),
                emptyToNull(attributes.get(KEY_FOLDER_KEY)),
                emptyToNull(attributes.get(KEY_PROVIDER_MESSAGE_KEY)),
                emptyToNull(attributes.get(KEY_PROVIDER_THREAD_KEY)),
                providerAttributes
        );
    }

    public static Map<String, String> merge(Map<String, String> baseAttributes, MailProviderEnvelope envelope) {
        Map<String, String> merged = new LinkedHashMap<>();
        if (baseAttributes != null && !baseAttributes.isEmpty()) {
            merged.putAll(baseAttributes);
        }
        if (envelope == null) {
            return merged;
        }
        merged.put(KEY_PROVIDER_TYPE, envelope.providerType().name());
        putIfHasText(merged, KEY_ACCOUNT_KEY, envelope.accountKey());
        putIfHasText(merged, KEY_FOLDER_KEY, envelope.folderKey());
        putIfHasText(merged, KEY_PROVIDER_MESSAGE_KEY, envelope.providerMessageKey());
        putIfHasText(merged, KEY_PROVIDER_THREAD_KEY, envelope.providerThreadKey());
        if (envelope.providerAttributes() != null) {
            envelope.providerAttributes().forEach((key, value) -> putIfHasText(merged, KEY_PREFIX_PROVIDER_ATTRIBUTE + key, value));
        }
        return merged;
    }

    private static MailProviderType parseProviderType(String raw) {
        if (raw == null || raw.isBlank()) {
            return MailProviderType.GENERIC;
        }
        try {
            return MailProviderType.valueOf(raw.trim().toUpperCase());
        } catch (IllegalArgumentException ex) {
            return MailProviderType.GENERIC;
        }
    }

    private static void putIfHasText(Map<String, String> target, String key, String value) {
        if (value != null && !value.isBlank()) {
            target.put(key, value);
        }
    }

    private static String emptyToNull(String value) {
        return value == null || value.isBlank() ? null : value;
    }
}
