package com.hiveops.aria.service;

import com.hiveops.aria.dto.ThreatEventIngestionRequest;
import com.hiveops.aria.dto.ThreatEventItem;
import com.hiveops.aria.entity.ThreatEvent;
import com.hiveops.aria.kafka.AriaThreatEvent;
import com.hiveops.aria.kafka.AriaThreatProducer;
import com.hiveops.aria.repository.ThreatEventRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.util.UUID;

@Service
@RequiredArgsConstructor
@Slf4j
public class ThreatEventIngestionService {

    private final ThreatEventRepository eventRepository;
    private final ThreatEventClassifier classifier;
    private final AriaThreatProducer producer;

    @Transactional
    public void ingest(ThreatEventIngestionRequest request) {
        for (ThreatEventItem item : request.getEvents()) {
            try {
                processEvent(request, item);
            } catch (Exception e) {
                log.error("Failed to process event {} from {}: {}",
                        item.getSignalKey(), request.getDeviceAgentId(), e.getMessage(), e);
            }
        }
    }

    private void processEvent(ThreatEventIngestionRequest request, ThreatEventItem item) {
        ThreatEventClassifier.ClassificationResult result = classifier.classify(item);

        ThreatEvent.EventType eventType;
        try {
            eventType = ThreatEvent.EventType.valueOf(item.getEventType());
        } catch (IllegalArgumentException e) {
            eventType = ThreatEvent.EventType.OS_EVENT;
        }

        ThreatEvent event = ThreatEvent.builder()
                .deviceId(request.getDeviceId())
                .deviceAgentId(request.getDeviceAgentId())
                .eventType(eventType)
                .signalKey(item.getSignalKey())
                .rawPayload(item.getRawPayload())
                .matchedIoc(result.matchedIoc())
                .severity(result.severity())
                .detectedAt(item.getDetectedAt() != null ? item.getDetectedAt() : Instant.now())
                .attackPhase(result.attackPhase())
                .institutionKey(request.getInstitutionKey())
                .build();

        eventRepository.save(event);

        log.info("ARIA event ingested: device={} signal={} severity={} phase={}",
                request.getDeviceAgentId(), item.getSignalKey(), result.severity(), result.attackPhase());

        // Publish HIGH and above to Kafka so any service (incident, future consumers) can react
        if (shouldPublish(result.severity())) {
            publishToKafka(event, result);
        }
    }

    private boolean shouldPublish(ThreatEvent.ThreatSeverity severity) {
        return severity == ThreatEvent.ThreatSeverity.CRITICAL
                || severity == ThreatEvent.ThreatSeverity.HIGH;
    }

    private void publishToKafka(ThreatEvent event, ThreatEventClassifier.ClassificationResult result) {
        String description = buildDescription(event, result);

        AriaThreatEvent kafkaEvent = AriaThreatEvent.builder()
                .eventId(UUID.randomUUID())
                .deviceId(event.getDeviceId())
                .deviceAgentId(event.getDeviceAgentId())
                .institutionKey(event.getInstitutionKey())
                .signalKey(event.getSignalKey())
                .eventType(event.getEventType().name())
                .severity(event.getSeverity().name())
                .description(description)
                .matchedIocValue(result.matchedIoc() != null ? result.matchedIoc().getValue() : null)
                .matchedIocType(result.matchedIoc() != null ? result.matchedIoc().getIocType().name() : null)
                .attackPhase(event.getAttackPhase() != null ? event.getAttackPhase().name() : null)
                .sequenceId(event.getSequenceId())
                .detectedAt(event.getDetectedAt())
                .sourceService("hiveops-aria")
                .build();

        producer.publishThreatEvent(kafkaEvent);
    }

    private String buildDescription(ThreatEvent event, ThreatEventClassifier.ClassificationResult result) {
        StringBuilder sb = new StringBuilder();
        sb.append("ARIA threat signal detected: ").append(event.getSignalKey());

        if (result.matchedIoc() != null) {
            sb.append(" — IOC match: ").append(result.matchedIoc().getValue());
            if (result.matchedIoc().getDescription() != null) {
                sb.append(" (").append(result.matchedIoc().getDescription()).append(")");
            }
        }

        if (result.attackPhase() != null) {
            sb.append(" [Phase: ").append(result.attackPhase().name()).append("]");
        }

        return sb.toString();
    }
}
