package com.rjconsultores.ventaboletos.service.impl;

import java.util.Calendar;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.rjconsultores.ventaboletos.dao.LogAuditoriaDAO;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.entidad.LogAuditoria;
import com.rjconsultores.ventaboletos.service.LogAuditoriaService;
import com.rjconsultores.ventaboletos.utilerias.UsuarioLogado;

import br.com.rjconsultores.auditador.auditadores.Auditador;
import br.com.rjconsultores.auditador.enums.AuditadorTipoAlteracao;
import br.com.rjconsultores.auditador.model.AuditadorObjects;

@Service("LogAuditoriaService")
public class LogAuditoriaServiceImpl implements LogAuditoriaService {
	
	private static final Logger log = LogManager.getLogger(LogAuditoriaServiceImpl.class);
	
	@Autowired
	private LogAuditoriaDAO logAuditoriaDAO;

	@Override
	public List<LogAuditoria> obtenerTodos() {
		return logAuditoriaDAO.obtenerTodos();
	}

	@Override
	public LogAuditoria obtenerID(Long id) {
		return logAuditoriaDAO.obtenerID(id);
	}

	@Override
	@Transactional
	public LogAuditoria suscribir(LogAuditoria entidad) {
		entidad.setUsuario(UsuarioLogado.getUsuarioLogado());
		entidad.setFecmodif(Calendar.getInstance().getTime());
		entidad.setActivo(Boolean.TRUE);
		return logAuditoriaDAO.suscribir(entidad);
	}

	@Override
	@Transactional
	public LogAuditoria actualizacion(LogAuditoria entidad) {
		entidad.setUsuario(UsuarioLogado.getUsuarioLogado());
		entidad.setFecmodif(Calendar.getInstance().getTime());
		entidad.setActivo(Boolean.TRUE);
		return logAuditoriaDAO.actualizacion(entidad);
	}

	@Override
	@Transactional
	public void borrar(LogAuditoria entidad) {
		entidad.setUsuario(UsuarioLogado.getUsuarioLogado());
		entidad.setFecmodif(Calendar.getInstance().getTime());
		entidad.setActivo(Boolean.FALSE);
		logAuditoriaDAO.actualizacion(entidad);
	}

	@Override
	@Transactional
	public void auditar(Object original, Object novo, Integer empresaId) {
		try {
			log.info(String.format(":: Iniciando gravação registros de auditoria classe: %s", novo.getClass().getSimpleName()));
			Integer totalRegistrosAuditados = 0;
			List<AuditadorObjects> lista = Auditador.getInstance().auditar(original, novo);
			if(lista != null && !lista.isEmpty()) {
				suscribir(lista, empresaId);
				totalRegistrosAuditados = lista.size();
			}
			log.info(String.format(":: Fim gravação registros de auditoria classe: %s - Total Registros auditados: %d", novo.getClass().getSimpleName(), totalRegistrosAuditados));
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
	}

	private LogAuditoria convertToLogAuditoria(AuditadorObjects log, Integer empresaId) {
		LogAuditoria logAuditoria = new LogAuditoria();
		logAuditoria.setUsuario(UsuarioLogado.getUsuarioLogado());
		logAuditoria.setFecmodif(Calendar.getInstance().getTime());
		logAuditoria.setActivo(Boolean.TRUE);
		logAuditoria.setCampoAlterado(log.getCampoAlterado() != null ? log.getCampoAlterado().toUpperCase() : null);
		logAuditoria.setClasseAlterada(log.getClasseAlterada());
		logAuditoria.setClassePrincipal(log.getClassePrincipal());
		logAuditoria.setTela(log.getTela());
		logAuditoria.setTipoAlteracao(log.getTipoAlteracao() != null ? log.getTipoAlteracao().toString() : AuditadorTipoAlteracao.ALTERACAO.toString());
		logAuditoria.setValorAnterior(log.getValorAnterior() != null ? log.getValorAnterior().toUpperCase() : null);
		logAuditoria.setValorNovo(log.getValorNovo() != null ? log.getValorNovo().toUpperCase() : null);
		logAuditoria.setIdAuditado(log.getIdAuditado());
		
		if(empresaId != null) {
			logAuditoria.setEmpresa(new Empresa(empresaId));
		}
		return logAuditoria;
	}

	@Override
	@Transactional
	public void auditarExclusao(Object objeto, Integer empresaId) {
		try {
			log.info(String.format(":: Iniciando gravação registros de auditoria de exclusao classe: %s", objeto.getClass().getSimpleName()));
			Integer totalRegistrosAuditados = 0;
			List<AuditadorObjects> lista = Auditador.getInstance().auditarExclusao(objeto);
			if(lista != null && !lista.isEmpty()) {
				suscribir(lista, empresaId);
				totalRegistrosAuditados = lista.size();
			}
			log.info(String.format(":: Fim gravação registros de auditoria de exclusao classe: %s - Total Registros auditados: %d", objeto.getClass().getSimpleName(), totalRegistrosAuditados));
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}		
	}

	@Override
	public List<String> listarTodasAsTelas() {
		return logAuditoriaDAO.listarTodasAsTelas();
	}

	@Override
	@Transactional
	public void suscribir(List<AuditadorObjects> lsObjects, Integer empresaId) {
		for (AuditadorObjects auditado : lsObjects) {
			LogAuditoria logAuditoria = convertToLogAuditoria(auditado, empresaId);
			suscribir(logAuditoria);
		}
	}

}
