package de.jottyfan.camporganizer.module.business.privileges;

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.List;
import java.util.Set;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jooq.DSLContext;
import org.jooq.DeleteConditionStep;
import org.jooq.InsertReturningStep;
import org.jooq.Record5;
import org.jooq.Record8;
import org.jooq.SelectSeekStep3;
import org.jooq.impl.DSL;
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.EnumModule;
import de.jottyfan.camporganizer.db.jooq.tables.records.TCampprofileRecord;
import de.jottyfan.camporganizer.module.business.privileges.model.BusinessPrivilegesBean;
import de.jottyfan.camporganizer.module.business.privileges.model.ProfileBean;

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

	@Autowired
	private DSLContext jooq;

	public List<BusinessPrivilegesBean> getPrivileges() {
		SelectSeekStep3<Record8<String, String, LocalDateTime, String, Integer, Integer, String, Double>, LocalDateTime, String, String> sql = jooq
		// @formatter:off
			.select(T_PROFILE.FORENAME, T_PROFILE.SURNAME, T_PROFILE.DUEDATE, T_PROFILE.USERNAME, T_PROFILE.PK, V_CAMP.PK, V_CAMP.NAME, V_CAMP.YEAR)
			.from(V_CAMP)
			.leftJoin(T_CAMPPROFILE).on(T_CAMPPROFILE.FK_CAMP.eq(V_CAMP.PK)).and(T_CAMPPROFILE.MODULE.eq(EnumModule.business))
			.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_CAMPPROFILE.FK_PROFILE))
			.orderBy(V_CAMP.ARRIVE, T_PROFILE.SURNAME, T_PROFILE.FORENAME);
		// @formatter:on
		LOGGER.trace(sql);
		List<BusinessPrivilegesBean> list = new ArrayList<>();
		for (Record8<String, String, LocalDateTime, String, Integer, Integer, String, Double> r : sql.fetch()) {
			BusinessPrivilegesBean bean = new BusinessPrivilegesBean();
			bean.setCampName(r.get(V_CAMP.NAME));
			bean.setCampYear(r.get(V_CAMP.YEAR));
			bean.setFkCamp(r.get(V_CAMP.PK));
			bean.setFkProfile(r.get(T_PROFILE.PK));
			bean.setForename(r.get(T_PROFILE.FORENAME));
			bean.setSurname(r.get(T_PROFILE.SURNAME));
			bean.setUsername(r.get(T_PROFILE.USERNAME));
			bean.setDuedate(r.get(T_PROFILE.DUEDATE));
			list.add(bean);
		}
		return list;
	}

	public List<ProfileBean> getProfiles(Set<String> allowed) {
		SelectSeekStep3<Record5<Integer, String, String, LocalDateTime, String>, String, String, LocalDateTime> sql = jooq
		// @formatter:off
			.select(T_PROFILE.PK,
					    T_PROFILE.FORENAME,
					    T_PROFILE.SURNAME,
					    T_PROFILE.DUEDATE,
					    T_PROFILE.USERNAME)
			.from(T_PROFILE)
			.leftJoin(T_PERSON).on(T_PERSON.FK_PROFILE.eq(T_PROFILE.PK))
			.where((allowed == null || allowed.size() < 1) ? DSL.trueCondition() : T_PERSON.CAMPROLE.in(allowed))
			.orderBy(T_PROFILE.SURNAME, T_PROFILE.FORENAME, T_PROFILE.DUEDATE);
		// @formatter:on
		LOGGER.trace(sql);
		List<ProfileBean> list = new ArrayList<>();
		for (Record5<Integer, String, String, LocalDateTime, String> r : sql.fetch()) {
			ProfileBean bean = new ProfileBean();
			bean.setPk(r.get(T_PROFILE.PK));
			bean.setForename(r.get(T_PROFILE.FORENAME));
			bean.setSurname(r.get(T_PROFILE.SURNAME));
			bean.setUsername(r.get(T_PROFILE.USERNAME));
			bean.setDuedate(r.get(T_PROFILE.DUEDATE));
			list.add(bean);
		}
		return list;
	}

	public Integer add(BusinessPrivilegesBean bean) {
		InsertReturningStep<TCampprofileRecord> sql = jooq
		// @formatter:off
			.insertInto(T_CAMPPROFILE, T_CAMPPROFILE.FK_CAMP, T_CAMPPROFILE.FK_PROFILE, T_CAMPPROFILE.MODULE)
			.values(bean.getFkCamp(), bean.getFkProfile(), EnumModule.business)
			.onConflict(T_CAMPPROFILE.FK_CAMP, T_CAMPPROFILE.FK_PROFILE, T_CAMPPROFILE.MODULE)
			.doNothing();
		// @formatter:on
		LOGGER.trace(sql);
		return sql.execute();
	}

	public Integer remove(BusinessPrivilegesBean bean, String currentUser) {
		DeleteConditionStep<TCampprofileRecord> sql = jooq
		// @formatter:off
			.deleteFrom(T_CAMPPROFILE)
			.where(T_CAMPPROFILE.MODULE.eq(EnumModule.business))
			.and(T_CAMPPROFILE.FK_CAMP.eq(bean.getFkCamp()))
			.and(T_CAMPPROFILE.FK_PROFILE.eq(bean.getFkProfile()))
			.and(T_CAMPPROFILE.FK_PROFILE.notIn(jooq
				.select(T_PROFILE.PK)
				.from(T_PROFILE)
				.where(T_PROFILE.USERNAME.eq(currentUser))));
		// @formatter:on
		LOGGER.trace(sql);
		return sql.execute();
	}
}
