package com.arena.combat.service;

import com.arena.combat.dto.request.AuditoriaEventoRequest;
import com.arena.combat.entity.AuditoriaEvento;
import com.arena.combat.entity.PartidaCombate;
import com.arena.combat.entity.Usuario;
import com.arena.combat.repository.AuditoriaEventoRepository;
import com.arena.combat.repository.PartidaCombateRepository;
import com.arena.combat.repository.UsuarioRepository;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@RequiredArgsConstructor
@Slf4j
public class AuditoriaService {

    private final AuditoriaEventoRepository auditoriaEventoRepository;
    private final UsuarioRepository usuarioRepository;
    private final PartidaCombateRepository partidaCombateRepository;
    private final ObjectMapper objectMapper;

    @Transactional
    public AuditoriaEvento registrarEvento(AuditoriaEventoRequest request, HttpServletRequest httpRequest) {
        Usuario usuario = null;
        if (request.getUsuarioId() != null) {
            usuario = usuarioRepository.findById(request.getUsuarioId()).orElse(null);
        }

        PartidaCombate partida = null;
        if (request.getPartidaId() != null) {
            partida = partidaCombateRepository.findById(request.getPartidaId()).orElse(null);
        }

        String metadataJson = null;
        if (request.getMetadata() != null && !request.getMetadata().isEmpty()) {
            try {
                metadataJson = objectMapper.writeValueAsString(request.getMetadata());
            } catch (Exception e) {
                metadataJson = request.getMetadata().toString();
            }
        }

        String clientIp = httpRequest != null ? httpRequest.getRemoteAddr() : "127.0.0.1";
        String userAgent = httpRequest != null ? httpRequest.getHeader("User-Agent") : "Unknown";

        AuditoriaEvento evento = AuditoriaEvento.builder()
                .usuario(usuario)
                .partida(partida)
                .tipoEvento(request.getTipoEvento())
                .elementoOrigen(request.getElementoOrigen())
                .metadataJson(metadataJson)
                .ipOrigen(clientIp)
                .userAgent(userAgent != null && userAgent.length() > 250 ? userAgent.substring(0, 250) : userAgent)
                .build();

        AuditoriaEvento guardado = auditoriaEventoRepository.save(evento);
        log.debug("Evento de auditoría registrado: tipo={}, origen={}", request.getTipoEvento(), request.getElementoOrigen());
        return guardado;
    }

    @Transactional(readOnly = true)
    public List<AuditoriaEvento> listarEventosPorUsuario(Long usuarioId) {
        return auditoriaEventoRepository.findTop50ByUsuarioIdOrderByCreatedAtDesc(usuarioId);
    }

    @Transactional(readOnly = true)
    public List<AuditoriaEvento> listarUltimosEventos() {
        return auditoriaEventoRepository.findTop50ByOrderByCreatedAtDesc();
    }
}
