package de.jottyfan.camporganizer.module.business.camp.impl;

import static de.jottyfan.camporganizer.db.jooq.Tables.T_PERSON;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PROFILE;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_SALESPROFILE;
import static de.jottyfan.camporganizer.db.jooq.Tables.V_CAMP;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jooq.DSLContext;
import org.jooq.Record;
import org.jooq.Record6;
import org.jooq.Record8;
import org.jooq.SelectConditionStep;
import org.jooq.SelectSeekStep4;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
import de.jottyfan.camporganizer.db.jooq.enums.EnumSex;

/**
 *
 * @author jotty
 *
 */
@Repository
@Transactional(transactionManager = "transactionManager")
public class CampGateway {
	private static final Logger LOGGER = LogManager.getLogger(CampGateway.class);

	@Autowired
	private DSLContext jooq;

	/**
	 * get the camp referenced by pk
	 *
	 * @param pk       the ID of the camp
	 * @param username the name of the current user in this session
	 *
	 * @return the camp if found or null
	 */
	public CampBean getCamp(Integer pk, String username) {
		SelectConditionStep<Record6<String, Double, LocalDateTime, LocalDateTime, String, String>> sql = jooq
		// @formatter:off
			.select(V_CAMP.NAME, V_CAMP.YEAR, V_CAMP.ARRIVE, V_CAMP.DEPART, V_CAMP.LOCATION_NAME, V_CAMP.PRICE)
			.from(V_CAMP)
			.leftJoin(T_SALESPROFILE).on(T_SALESPROFILE.FK_CAMP.eq(V_CAMP.PK))
			.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_SALESPROFILE.FK_PROFILE))
			.where(V_CAMP.PK.eq(pk))
			.and(T_PROFILE.USERNAME.eq(username));
		// @formatter:on
		LOGGER.debug(sql.toString());
		CampBean bean = new CampBean();
		for (Record6<String, Double, LocalDateTime, LocalDateTime, String, String> r : sql.fetch()) {
			bean.setName(r.get(V_CAMP.NAME));
			bean.setYear(r.get(V_CAMP.YEAR));
			bean.setArrive(r.get(V_CAMP.ARRIVE));
			bean.setDepart(r.get(V_CAMP.DEPART));
			bean.setLocationName(r.get(V_CAMP.LOCATION_NAME));
			bean.setPrice(r.get(V_CAMP.PRICE));
		}
		return bean;
	}

	/**
	 * get a list of all registered persons that have booked the camp
	 *
	 * @param pk       the ID of the camp
	 * @param username the name of the current user in this session
	 *
	 * @return a list of bookings; an empty one at least
	 */
	public List<PersonBean> getBookings(Integer pk, String username) {
		SelectSeekStep4<Record8<Integer, Boolean, BigDecimal, String, String, EnumCamprole, EnumSex, LocalDateTime>, EnumCamprole, EnumSex, String, String> sql = jooq
		// @formatter:off
		  .select(T_PERSON.PK, T_PERSON.ACCEPT, T_PERSON.PAID, T_PERSON.FORENAME, T_PERSON.SURNAME, T_PERSON.CAMPROLE, T_PERSON.SEX, T_PERSON.CREATED)
		  .from(T_PERSON)
			.leftJoin(T_SALESPROFILE).on(T_SALESPROFILE.FK_CAMP.eq(T_PERSON.FK_CAMP))
			.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_SALESPROFILE.FK_PROFILE))
		  .where(T_PERSON.FK_CAMP.eq(pk))
		  .and(T_PROFILE.USERNAME.eq(username))
		  .orderBy(T_PERSON.CAMPROLE, T_PERSON.SEX, T_PERSON.SURNAME, T_PERSON.FORENAME);
		// @formatter:on
		LOGGER.debug(sql.toString());
		List<PersonBean> list = new ArrayList<>();
		for (Record r : sql.fetch()) {
			String forename = r.get(T_PERSON.FORENAME);
			String surname = r.get(T_PERSON.SURNAME);
			EnumCamprole role = r.get(T_PERSON.CAMPROLE);
			EnumSex sex = r.get(T_PERSON.SEX);
			PersonBean bean = new PersonBean();
			bean.setPk(r.get(T_PERSON.PK));
			bean.setName(String.format("%s %s", forename, surname));
			bean.setRole(EnumCamprole.student.equals(role) ? "Teilnehmer" : "Mitarbeiter");
			bean.setSex(EnumSex.female.equals(sex) ? "weiblich" : "männlich");
			bean.setBookingDate(r.get(T_PERSON.CREATED));
			bean.setAccept(r.get(T_PERSON.ACCEPT));
			bean.setPaid(r.get(T_PERSON.PAID));
			list.add(bean);
		}
		return list;
	}
}
