package de.jottyfan.camporganizer.module.confirmation.board;

import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMPPROFILE;
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.V_CAMP;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Iterator;
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.Record2;
import org.jooq.Record6;
import org.jooq.SelectConditionStep;
import org.jooq.SelectSeekStep1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import de.jottyfan.camporganizer.db.jooq.enums.EnumModule;
import de.jottyfan.camporganizer.db.jooq.enums.EnumProgress;
import de.jottyfan.camporganizer.db.jooq.enums.EnumSex;
import de.jottyfan.camporganizer.module.confirmation.board.model.CampBean;
import de.jottyfan.camporganizer.module.confirmation.board.model.PersonBean;
import de.jottyfan.camporganizer.module.confirmation.confirmation.ConfirmationRepository;

/**
 *
 * @author jotty
 *
 */
@Repository
public class ConfirmationBoardRepository {
	private static final Logger LOGGER = LogManager.getLogger(ConfirmationRepository.class);

	@Autowired
	private DSLContext jooq;

	/**
	 * get a list of camps that the user has access to
	 *
	 * @param username the username
	 * @return the list of camps; might be an empty list
	 */
	public List<CampBean> getCamps(String username) {
		SelectSeekStep1<Record6<String, Double, Boolean, String, Integer, LocalDateTime>, LocalDateTime> sql = jooq
		// @formatter:off
			.select(V_CAMP.NAME, V_CAMP.YEAR, V_CAMP.IS_OVER, V_CAMP.LOCATION_NAME, V_CAMP.PK, V_CAMP.ARRIVE)
			.from(T_PROFILE)
			.leftJoin(T_CAMPPROFILE).on(T_CAMPPROFILE.FK_PROFILE.eq(T_PROFILE.PK)).and(T_CAMPPROFILE.MODULE.eq(EnumModule.registration))
			.leftJoin(V_CAMP).on(V_CAMP.PK.eq(T_CAMPPROFILE.FK_CAMP))
			.where(T_PROFILE.USERNAME.eq(username))
			.orderBy(V_CAMP.ARRIVE);
		// @formatter:on
		LOGGER.trace(sql);
		List<CampBean> list = new ArrayList<>();
		Iterator<Record6<String, Double, Boolean, String, Integer, LocalDateTime>> i = sql.fetch().iterator();
		while (i.hasNext()) {
			Record6<String, Double, Boolean, String, Integer, LocalDateTime> r = i.next();
			CampBean bean = new CampBean();
			bean.setPkCamp(r.get(V_CAMP.PK));
			bean.setName(r.get(V_CAMP.NAME));
			bean.setYear(r.get(V_CAMP.YEAR));
			bean.setLocationName(r.get(V_CAMP.LOCATION_NAME));
			bean.setIsOver(r.get(V_CAMP.IS_OVER));
			list.add(bean);
		}
		return list;
	}

	/**
	 * get the list of persons for this camp; restrict by the user privilege
	 *
	 * @param username the user that needs access to this data
	 * @param campId   the ID of the camp
	 * @return the list of persons; an empty list at least
	 */
	public List<PersonBean> getPersons(String username, Integer campId) {
		SelectConditionStep<Record> sql = jooq
		// @formatter:off
			.select(T_PERSON.fields())
			.from(T_PERSON)
			.innerJoin(T_CAMPPROFILE).on(T_CAMPPROFILE.FK_CAMP.eq(T_PERSON.FK_CAMP)).and(T_CAMPPROFILE.MODULE.eq(EnumModule.registration))
			.innerJoin(T_PROFILE).on(T_PROFILE.USERNAME.eq(username)).and(T_PROFILE.PK.eq(T_CAMPPROFILE.FK_PROFILE))
			.where(T_PERSON.FK_CAMP.eq(campId));
		// @formatter:on
		LOGGER.trace(sql);
		List<PersonBean> list = new ArrayList<>();
		Iterator<Record> i = sql.fetch().iterator();
		while (i.hasNext()) {
			Record r = i.next();
			PersonBean bean = new PersonBean();
			EnumProgress progress = r.get(T_PERSON.PROGRESS);
			bean.setProgress(progress == null ? null : progress.getLiteral());
			bean.setBirthDate(r.get(T_PERSON.BIRTHDATE));
			bean.setCamprole(r.get(T_PERSON.CAMPROLE) == null ? null : r.get(T_PERSON.CAMPROLE).getLiteral());
			bean.setCity(r.get(T_PERSON.CITY));
			bean.setComment(r.get(T_PERSON.COMMENT));
			bean.setConsentCatalogPhoto(r.get(T_PERSON.CONSENT_CATALOG_PHOTO));
			bean.setCreated(r.get(T_PERSON.CREATED));
			bean.setEmail(r.get(T_PERSON.EMAIL));
			bean.setForename(r.get(T_PERSON.FORENAME));
			bean.setPaid(r.get(T_PERSON.PAID) == null ? null : r.get(T_PERSON.PAID).doubleValue());
			bean.setPhone(r.get(T_PERSON.PHONE));
			bean.setSex(r.get(T_PERSON.SEX) == null ? null : (r.get(T_PERSON.SEX).equals(EnumSex.male) ? "männlich" : "weiblich"));
			bean.setStreet(r.get(T_PERSON.STREET));
			bean.setSurname(r.get(T_PERSON.SURNAME));
			bean.setZip(r.get(T_PERSON.ZIP));
			list.add(bean);
		}
		return list;
	}

	/**
	 * get the camp start date of campId if username is allowed to
	 *
	 * @param username the user
	 * @param campId   the ID of the camp
	 * @return the camp start time or null
	 */
	public LocalDateTime getCampStartDate(String username, Integer campId) {
		SelectConditionStep<Record2<String, LocalDateTime>> sql = jooq
		// @formatter:off
			.select(V_CAMP.NAME, V_CAMP.ARRIVE)
			.from(T_PROFILE)
			.leftJoin(T_CAMPPROFILE).on(T_CAMPPROFILE.FK_PROFILE.eq(T_PROFILE.PK)).and(T_CAMPPROFILE.MODULE.eq(EnumModule.registration))
			.leftJoin(V_CAMP).on(V_CAMP.PK.eq(T_CAMPPROFILE.FK_CAMP))
			.where(T_PROFILE.USERNAME.eq(username))
			.and(V_CAMP.PK.eq(campId));
		// @formatter:on
		LOGGER.trace(sql);
		Iterator<Record2<String, LocalDateTime>> i = sql.fetch().iterator();
		while (i.hasNext()) {
			return i.next().get(V_CAMP.ARRIVE);
		}
		return null;
	}
}
