package mcp.server.zap.core.gateway;

import java.net.URI;
import java.util.Locale;
import org.springframework.stereotype.Component;

/**
 * Builds normalized gateway records without changing the public ZAP tool surface.
 */
@Component
public class GatewayRecordFactory {

    public void requireCapability(EngineAdapter engineAdapter,
                                  EngineCapability capability,
                                  String operationLabel) {
        if (engineAdapter == null || capability == null) {
            throw new IllegalStateException("Gateway engine capability check is misconfigured.");
        }
        if (!engineAdapter.supports(capability)) {
            String engineId = hasText(engineAdapter.engineId()) ? engineAdapter.engineId() : "unknown";
            String engineName = hasText(engineAdapter.displayName()) ? engineAdapter.displayName() : engineId;
            throw new UnsupportedEngineCapabilityException(
                    engineId,
                    engineName,
                    capability,
                    readableOperation(operationLabel, capability)
            );
        }
    }

    public TargetDescriptor targetFromUrl(String targetUrl, TargetDescriptor.Kind kind) {
        String normalized = requireText(targetUrl, "targetUrl");
        try {
            URI uri = URI.create(normalized);
            if (hasText(uri.getScheme()) && hasText(uri.getHost())) {
                String host = uri.getHost().toLowerCase(Locale.ROOT);
                String path = hasText(uri.getPath()) ? uri.getPath() : "";
                String authority = uri.getPort() >= 0 ? host + ":" + uri.getPort() : host;
                String baseUrl = uri.getScheme().toLowerCase(Locale.ROOT) + "://" + authority + path;
                return new TargetDescriptor(kind, baseUrl, host);
            }
        } catch (IllegalArgumentException ignored) {
            // Fall through to hostname-style normalization for non-URL targets.
        }

        String displayName = normalized.toLowerCase(Locale.ROOT);
        return new TargetDescriptor(kind, displayName, displayName);
    }

    public TargetDescriptor optionalTarget(String targetUrl, TargetDescriptor.Kind kind) {
        if (!hasText(targetUrl)) {
            return new TargetDescriptor(kind, null, "All targets");
        }
        return targetFromUrl(targetUrl, kind);
    }

    public ScanRunRecord scanRun(EngineAdapter engineAdapter,
                                 String runId,
                                 String operationKind,
                                 String status,
                                 TargetDescriptor target,
                                 String executionMode,
                                 String backendReference) {
        return new ScanRunRecord(
                engineAdapter.engineId(),
                runId,
                operationKind,
                status,
                target,
                executionMode,
                backendReference
        );
    }

    public FindingRecord findingSummary(EngineAdapter engineAdapter,
                                        TargetDescriptor target,
                                        String category) {
        return new FindingRecord(
                engineAdapter.engineId(),
                "guided-findings-summary",
                "mixed",
                "Guided findings summary",
                target,
                category,
                "Summary generated by the active engine"
        );
    }

    public ArtifactRecord reportArtifact(EngineAdapter engineAdapter,
                                         TargetDescriptor target,
                                         String location,
                                         String reportFormat) {
        String normalizedFormat = hasText(reportFormat) ? reportFormat.trim().toLowerCase(Locale.ROOT) : "html";
        return new ArtifactRecord(
                engineAdapter.engineId(),
                location,
                "report",
                location,
                "json".equals(normalizedFormat) ? "application/json" : "text/html",
                target
        );
    }

    private String readableOperation(String operationLabel, EngineCapability capability) {
        if (hasText(operationLabel)) {
            return operationLabel.trim();
        }
        return capability.name().toLowerCase(Locale.ROOT).replace('_', ' ');
    }

    private String requireText(String value, String fieldName) {
        if (!hasText(value)) {
            throw new IllegalArgumentException(fieldName + " cannot be null or blank");
        }
        return value.trim();
    }

    private boolean hasText(String value) {
        return value != null && !value.trim().isEmpty();
    }
}
