package br.gov.sigefp.admin.service;

import br.gov.sigefp.admin.api.dto.AuditLogDTO;
import br.gov.sigefp.admin.domain.UserAccount;
import br.gov.sigefp.common.domain.AuditLog;
import br.gov.sigefp.common.repository.AuditLogRepository;
import br.gov.sigefp.admin.repository.UserAccountRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * Serviço de aplicação para gestão de logs de auditoria.
 */
@Service
@RequiredArgsConstructor
@Transactional
public class AuditLogService {

    private final AuditLogRepository auditLogRepository;
    private final UserAccountRepository userAccountRepository;

    /**
     * Registra um log de auditoria.
     * Pode ser usado por outros módulos.
     */
    public AuditLogDTO logAction(UUID userId, String module, String action, String entity, UUID entityId,
            String description) {
        String username = "system";
        if (userId != null) {
            username = userAccountRepository.findById(userId)
                    .map(UserAccount::getUsername)
                    .orElse("unknown");
        }

        AuditLog auditLog = AuditLog.builder()
                .userId(userId)
                .username(username)
                .module(module)
                .action(action)
                .entity(entity)
                .entityId(entityId)
                .description(description)
                .build();

        AuditLog saved = auditLogRepository.save(auditLog);
        return toDTO(saved);
    }

    /**
     * Consulta logs com filtros opcionais.
     */
    @Transactional(readOnly = true)
    public Page<AuditLogDTO> findLogs(UUID userId, String module, Instant startDate, Instant endDate,
            Pageable pageable) {
        Page<AuditLog> logs;

        if (userId != null && module != null && startDate != null && endDate != null) {
            logs = auditLogRepository.findByUserIdAndModuleAndCreatedAtBetween(userId, module, startDate, endDate,
                    pageable);
        } else if (userId != null && module != null) {
            logs = auditLogRepository.findByUserIdAndModule(userId, module, pageable);
        } else if (userId != null) {
            logs = auditLogRepository.findByUserId(userId, pageable);
        } else if (module != null) {
            logs = auditLogRepository.findByModule(module, pageable);
        } else if (startDate != null && endDate != null) {
            logs = auditLogRepository.findByCreatedAtBetween(startDate, endDate, pageable);
        } else {
            logs = auditLogRepository.findAll(pageable);
        }

        return logs.map(this::toDTO);
    }

    private AuditLogDTO toDTO(AuditLog log) {
        return AuditLogDTO.builder()
                .id(log.getId())
                .userId(log.getUserId())
                .userUsername(log.getUsername())
                .module(log.getModule())
                .action(log.getAction())
                .entity(log.getEntity())
                .entityId(log.getEntityId())
                .description(log.getDescription())
                .createdAt(log.getCreatedAt())
                .build();
    }
}
