package com.cameleer.server.core.license;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.security.*;
import java.security.spec.X509EncodedKeySpec;
import java.time.Instant;
import java.util.*;

public class LicenseValidator {

    private static final Logger log = LoggerFactory.getLogger(LicenseValidator.class);
    private static final ObjectMapper objectMapper = new ObjectMapper();

    private final PublicKey publicKey;

    public LicenseValidator(String publicKeyBase64) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(publicKeyBase64);
            KeyFactory kf = KeyFactory.getInstance("Ed25519");
            this.publicKey = kf.generatePublic(new X509EncodedKeySpec(keyBytes));
        } catch (Exception e) {
            throw new IllegalStateException("Failed to load license public key", e);
        }
    }

    public LicenseInfo validate(String token) {
        String[] parts = token.split("\\.", 2);
        if (parts.length != 2) {
            throw new IllegalArgumentException("Invalid license token format: expected payload.signature");
        }

        byte[] payloadBytes = Base64.getDecoder().decode(parts[0]);
        byte[] signatureBytes = Base64.getDecoder().decode(parts[1]);

        // Verify signature
        try {
            Signature verifier = Signature.getInstance("Ed25519");
            verifier.initVerify(publicKey);
            verifier.update(payloadBytes);
            if (!verifier.verify(signatureBytes)) {
                throw new SecurityException("License signature verification failed");
            }
        } catch (SecurityException e) {
            throw e;
        } catch (Exception e) {
            throw new SecurityException("License signature verification failed", e);
        }

        // Parse payload
        try {
            JsonNode root = objectMapper.readTree(payloadBytes);

            String tier = root.get("tier").asText();

            Set<Feature> features = new HashSet<>();
            if (root.has("features")) {
                for (JsonNode f : root.get("features")) {
                    try {
                        features.add(Feature.valueOf(f.asText()));
                    } catch (IllegalArgumentException e) {
                        log.warn("Unknown feature in license: {}", f.asText());
                    }
                }
            }

            Map<String, Integer> limits = new HashMap<>();
            if (root.has("limits")) {
                root.get("limits").fields().forEachRemaining(entry ->
                        limits.put(entry.getKey(), entry.getValue().asInt()));
            }

            Instant issuedAt = root.has("iat") ? Instant.ofEpochSecond(root.get("iat").asLong()) : Instant.now();
            Instant expiresAt = root.has("exp") ? Instant.ofEpochSecond(root.get("exp").asLong()) : null;

            LicenseInfo info = new LicenseInfo(tier, features, limits, issuedAt, expiresAt);

            if (info.isExpired()) {
                throw new IllegalArgumentException("License expired at " + expiresAt);
            }

            return info;
        } catch (IllegalArgumentException e) {
            throw e;
        } catch (Exception e) {
            throw new IllegalArgumentException("Failed to parse license payload", e);
        }
    }
}
