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

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.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.DeleteConditionStep;
import org.jooq.InsertReturningStep;
import org.jooq.Record5;
import org.jooq.Record8;
import org.jooq.SelectSeekStep3;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import de.jottyfan.camporganizer.db.jooq.tables.records.TSalesprofileRecord;

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

	@Autowired
	private DSLContext jooq;

	public List<PrivilegesBean> 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_SALESPROFILE).on(T_SALESPROFILE.FK_CAMP.eq(V_CAMP.PK))
			.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_SALESPROFILE.FK_PROFILE))
			.orderBy(V_CAMP.ARRIVE, T_PROFILE.SURNAME, T_PROFILE.FORENAME);
		// @formatter:on
		LOGGER.debug(sql.toString());
		List<PrivilegesBean> list = new ArrayList<>();
		for (Record8<String, String, LocalDateTime, String, Integer, Integer, String, Double> r : sql.fetch()) {
			PrivilegesBean bean = new PrivilegesBean();
			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() {
		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)
			.orderBy(T_PROFILE.SURNAME, T_PROFILE.FORENAME, T_PROFILE.DUEDATE);
		// @formatter:on
		LOGGER.debug(sql.toString());
		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(PrivilegesBean bean) {
		InsertReturningStep<TSalesprofileRecord> sql = jooq
		// @formatter:off
			.insertInto(T_SALESPROFILE, T_SALESPROFILE.FK_CAMP, T_SALESPROFILE.FK_PROFILE)
			.values(bean.getFkCamp(), bean.getFkProfile())
			.onConflict(T_SALESPROFILE.FK_CAMP, T_SALESPROFILE.FK_PROFILE)
			.doNothing();
		// @formatter:on
		LOGGER.debug(sql.toString());
		return sql.execute();
	}

	public Integer remove(PrivilegesBean bean, String currentUser) {
		DeleteConditionStep<TSalesprofileRecord> sql = jooq
		// @formatter:off
			.deleteFrom(T_SALESPROFILE)
			.where(T_SALESPROFILE.FK_CAMP.eq(bean.getFkCamp()))
			.and(T_SALESPROFILE.FK_PROFILE.eq(bean.getFkProfile()))
			.and(T_SALESPROFILE.FK_PROFILE.notIn(jooq
				.select(T_PROFILE.PK)
				.from(T_PROFILE)
				.where(T_PROFILE.USERNAME.eq(currentUser))));
		// @formatter:on
		LOGGER.debug(sql.toString());
		return sql.execute();
	}
}
