package de.oaa.xxx.session;

import java.time.LocalDateTime;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.oaa.xxx.framework.request.RequestChecker;
import de.oaa.xxx.session.aufgaben.AufgabenList;
import de.oaa.xxx.session.entity.MitspielerDAO;
import de.oaa.xxx.session.entity.MitspielerEntity;
import de.oaa.xxx.session.entity.SessionDAO;
import de.oaa.xxx.session.entity.SessionEntity;
import jakarta.annotation.Resource;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.json.bind.JsonbBuilder;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.transaction.SystemException;
import jakarta.transaction.UserTransaction;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import jakarta.ws.rs.core.UriInfo;

@ApplicationScoped
@Path("session")
public class SessionResource {


	private Logger LOGGER = LoggerFactory.getLogger(getClass());
	
	@PersistenceContext(name = "aufgaben")
	private EntityManager entityManager;
	@Resource
	private UserTransaction transaction;
	
	@GET
	@Path("{sessionId}")
	@Produces(MediaType.APPLICATION_JSON)
	public Response getBySessionId(@PathParam("sessionId") UUID sessionId, @Context HttpServletRequest req) throws IllegalStateException, SecurityException, SystemException {
		try {
			RequestChecker.checkRequest(req);
			transaction.begin();
			SessionEntity entity = new SessionDAO(entityManager).findById(sessionId);
			if (entity != null) {
				Session session = new Session();
				session.setSessionId(entity.getSessionId());
				session.setUserId(entity.getUserId());
				session.setAufgabenProLevel(entity.getAufgabenAufAktuellemLevel());
				session.setWahrscheinlichkeitSperre(entity.getWahrscheinlichkeitSperre());
				session.setWahrscheinlichkeitStrafe(entity.getWahrscheinlichkeitStrafe());
				session.setZeitfaktorZeitstrafen(entity.getZeitfaktorZeitstrafen());
				transaction.commit();
				return Response.ok(session).build();
			} else {
				transaction.rollback();
				return Response.noContent().build();
			}
		} catch (Exception exception) {
			LOGGER.error(exception.getMessage(), exception);
			transaction.rollback();
			return Response.serverError().build();
		}
	}
	
	@GET
	@Produces(MediaType.APPLICATION_JSON)
	public Response getByUserId(@QueryParam("userId") UUID userId, @Context HttpServletRequest req) throws IllegalStateException, SecurityException, SystemException {
		try {
			RequestChecker.checkRequest(req);
			transaction.begin();
			SessionEntity entity = new SessionDAO(entityManager).findByUserId(userId);
			if (entity != null) {
				Session session = new Session();
				session.setSessionId(entity.getSessionId());
				session.setUserId(entity.getUserId());
				session.setAufgabenProLevel(entity.getAufgabenAufAktuellemLevel());
				session.setWahrscheinlichkeitSperre(entity.getWahrscheinlichkeitSperre());
				session.setWahrscheinlichkeitStrafe(entity.getWahrscheinlichkeitStrafe());
				session.setZeitfaktorZeitstrafen(entity.getZeitfaktorZeitstrafen());
				transaction.commit();
				return Response.ok(session).build();
			} else {
				transaction.rollback();
				return Response.noContent().build();
			}
		} catch (Exception exception) {
			LOGGER.error(exception.getMessage(), exception);
			transaction.rollback();
			return Response.serverError().build();
		}
	}
	
	@DELETE
	public Response deleteSession(Session session, @Context HttpServletRequest req) throws IllegalStateException, SecurityException, SystemException {
		try {
			RequestChecker.checkRequest(req);
			transaction.begin();
			SessionEntity entity = new SessionDAO(entityManager).findByUserId(session.getSessionId());
			if (entity != null) {
				new SessionDAO(entityManager).remove(entity);
				return Response.accepted().build();
			} else {
				transaction.rollback();
				return Response.noContent().build();
			}
		} catch (Exception exception) {
			LOGGER.error(exception.getMessage(), exception);
			transaction.rollback();
			return Response.serverError().build();
		}
	}
	
	@POST
	@Consumes(MediaType.APPLICATION_JSON)
	public Response create(Session session, @Context UriInfo uriInfo, @Context HttpServletRequest req) throws IllegalStateException, SecurityException, SystemException {
		try {
			UUID userId = RequestChecker.checkRequest(req).getUserId();
			transaction.begin();
			SessionEntity entity = new SessionEntity();
			entity.setSessionId(UUID.randomUUID());
			entity.setUserId(userId);
			entity.setAufgabenAufAktuellemLevel(0);
			entity.setAufgabenProLevel(session.getAufgabenProLevel() != null ? session.getAufgabenProLevel() : 5);
			LocalDateTime now = LocalDateTime.now();
			entity.setLetzteAktivitaet(now);
			entity.setStartZeit(now);
			entity.setWahrscheinlichkeitSperre(session.getWahrscheinlichkeitSperre() != null ? session.getWahrscheinlichkeitSperre() : 10);
			entity.setWahrscheinlichkeitStrafe(session.getWahrscheinlichkeitStrafe() != null ? session.getWahrscheinlichkeitStrafe() : 10);
			entity.setZeitfaktorZeitstrafen(session.getZeitfaktorZeitstrafen() != null ? session.getZeitfaktorZeitstrafen() : 1.0);
			new SessionDAO(entityManager).persist(entity);
			transaction.commit();
			return Response.created(uriInfo.getAbsolutePathBuilder().path(entity.getSessionId().toString()).build())
					.build();
		} catch (Exception exception) {
			LOGGER.error(exception.getMessage(), exception);
			transaction.rollback();
			return Response.serverError().build();
		}
	}
	
	@POST
	@Consumes(MediaType.APPLICATION_JSON)
	@Path("{sessionId}/aufgaben")
	public Response setAufgaben(AufgabenList list, @PathParam("sessionId") UUID sessionId, @Context HttpServletRequest req) throws IllegalStateException, SecurityException, SystemException {
		try {
			RequestChecker.checkRequest(req);
			if (list.size() > 1000) {
				return Response.status(Status.BAD_REQUEST).build();
			}
			String aufgaben = JsonbBuilder.create().toJson(list);
			transaction.begin();
			SessionDAO dao = new SessionDAO(entityManager);
			SessionEntity session = dao.findById(sessionId);
			if (session == null) {
				transaction.rollback();
				return Response.status(Status.BAD_REQUEST).build();
			}
			session.setAufgaben(aufgaben);
			dao.update(session);
			transaction.commit();
			return Response.accepted().build();
		} catch (Exception exception) {
			LOGGER.error(exception.getMessage(), exception);
			transaction.rollback();
			return Response.serverError().build();
		}
	}
	
	@GET
	@Produces(MediaType.APPLICATION_JSON)
	@Path("{sessionId}/aufgaben/next")
	public Response getNextAufgabe(@PathParam("sessionId") UUID sessionId, @Context HttpServletRequest req) throws IllegalStateException, SecurityException, SystemException {
		try {
			RequestChecker.checkRequest(req);
			transaction.begin();
			SessionDAO dao = new SessionDAO(entityManager);
			SessionEntity session = dao.findById(sessionId);
			if (session == null) {
				transaction.rollback();
				return Response.status(Status.BAD_REQUEST).build();
			}
			session.setLetzteAktivitaet(LocalDateTime.now());
			AufgabeAnzeige next = new SessionDurchfuehren(session).getNext();
			transaction.commit();
			return Response.ok(next).build();
		} catch (Exception exception) {
			LOGGER.error(exception.getMessage(), exception);
			transaction.rollback();
			return Response.serverError().build();
		}
	}
	
	@POST
	@Consumes(MediaType.APPLICATION_JSON)
	@Path("{sessionId}/mitspieler")
	public Response addMitspieler(Mitspieler mitspieler, @PathParam("sessionId") UUID sessionId, @Context HttpServletRequest req) throws IllegalStateException, SecurityException, SystemException {
		try {
			RequestChecker.checkRequest(req);
			if (mitspieler.getName() == null || mitspieler.getGeschlecht() == null || mitspieler.getRollen() == null 
					|| mitspieler.getRollen().isEmpty() || mitspieler.getSpieltMit() == null || mitspieler.getSpieltMit().isEmpty()
					|| mitspieler.getVerfuegbareWerkzeuge() == null || mitspieler.getVerfuegbareWerkzeuge().isEmpty()) {
				return Response.status(Status.BAD_REQUEST).build();
			}
			transaction.begin();
			SessionDAO dao = new SessionDAO(entityManager);
			SessionEntity session = dao.findById(sessionId);
			if (session == null) {
				transaction.rollback();
				return Response.status(Status.BAD_REQUEST).build();
			}
			
			MitspielerEntity entity = new MitspielerEntity();
			entity.setMitspielerId(UUID.randomUUID());
			entity.setGeschlecht(mitspieler.getGeschlecht());
			entity.setName(mitspieler.getName());
			entity.setRollen(mitspieler.getRollen());
			entity.setSpieltMit(mitspieler.getSpieltMit());
			entity.setWerkzeuge(mitspieler.getVerfuegbareWerkzeuge());
			entity.setSession(session);
			new MitspielerDAO(entityManager).persist(entity);
			transaction.commit();
			return Response.accepted().build();
		} catch (Exception exception) {
			LOGGER.error(exception.getMessage(), exception);
			transaction.rollback();
			return Response.serverError().build();
		}
	}
	
}
