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

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

import java.math.BigDecimal;
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.Record4;
import org.jooq.Record9;
import org.jooq.SelectConditionStep;
import org.jooq.SelectSeekStep1;
import org.jooq.UpdateConditionStep;
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.TPersonRecord;
import de.jottyfan.camporganizer.module.business.business.model.BusinessBean;
import de.jottyfan.camporganizer.module.business.business.model.CampBudgetBean;

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

	@Autowired
	private DSLContext jooq;

	/**
	 * get a list of all camp budgets of all years
	 *
	 * @param username the name of the user for privilege checks
	 *
	 * @return the list of all camp budgets
	 */
	public List<CampBudgetBean> getCampBudgets(String username) {
		SelectSeekStep1<Record4<BigDecimal, String, Double, Integer>, LocalDateTime> sql = jooq
		// @formatter:off
			.select(V_CAMP_BUDGET.BUDGET,
					    V_CAMP_BUDGET.CAMP_NAME,
					    V_CAMP_BUDGET.YEAR,
					    V_CAMP_BUDGET.FK_CAMP)
			.from(V_CAMP_BUDGET)
			.leftJoin(T_CAMP).on(T_CAMP.PK.eq(V_CAMP_BUDGET.FK_CAMP))
			.leftJoin(T_CAMPPROFILE).on(T_CAMPPROFILE.FK_CAMP.eq(V_CAMP_BUDGET.FK_CAMP)).and(T_CAMPPROFILE.MODULE.eq(EnumModule.business))
			.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_CAMPPROFILE.FK_PROFILE))
			.where(T_PROFILE.USERNAME.eq(username))
			.orderBy(T_CAMP.ARRIVE);
		// @formatter:on
		LOGGER.trace(sql);
		List<CampBudgetBean> list = new ArrayList<>();
		Iterator<Record4<BigDecimal, String, Double, Integer>> i = sql.fetch().iterator();
		while (i.hasNext()) {
			Record r = i.next();
			BigDecimal b = r.get(V_CAMP_BUDGET.BUDGET);
			String n = r.get(V_CAMP_BUDGET.CAMP_NAME);
			Double y = r.get(V_CAMP_BUDGET.YEAR);
			Integer c = r.get(V_CAMP_BUDGET.FK_CAMP);
			list.add(new CampBudgetBean().withBudget(b).withCampName(n).withCampYear(y).withCampId(c));
		}
		return list;
	}

	/**
	 * get all registrations for the search mask
	 *
	 * @param username the name of the user for privilege checks
	 *
	 * @return a list of business beans; an empty one at least
	 */
	public List<BusinessBean> getAllRegistrations(String username) {
		SelectConditionStep<Record9<Integer, String, String, String, String, LocalDateTime, String, BigDecimal, BigDecimal>> sql = jooq
		// @formatter:off
			.select(T_PERSON.PK,
					    T_PERSON.FORENAME,
					    T_PERSON.SURNAME,
					    T_CAMP.NAME,
					    T_CAMP.PRICE,
					    T_CAMP.ARRIVE,
					    T_LOCATION.NAME,
					    T_PERSON.PAID,
					    T_PERSON.REQUIRED_PRICE)
			.from(T_PERSON)
			.leftJoin(T_CAMP).on(T_CAMP.PK.eq(T_PERSON.FK_CAMP))
			.leftJoin(T_LOCATION).on(T_LOCATION.PK.eq(T_CAMP.FK_LOCATION))
			.leftJoin(T_CAMPPROFILE).on(T_CAMPPROFILE.FK_CAMP.eq(T_CAMP.PK)).and(T_CAMPPROFILE.MODULE.eq(EnumModule.business))
			.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_CAMPPROFILE.FK_PROFILE))
			.where(T_PROFILE.USERNAME.eq(username));
	  // @formatter:on
		LOGGER.trace(sql);
		List<BusinessBean> list = new ArrayList<>();
		Iterator<Record9<Integer, String, String, String, String, LocalDateTime, String, BigDecimal, BigDecimal>> i = sql.fetch().iterator();
		while (i.hasNext()) {
			Record9<Integer, String, String, String, String, LocalDateTime, String, BigDecimal, BigDecimal> r = i.next();
			Integer fkPerson = r.get(T_PERSON.PK);
			String forename = r.get(T_PERSON.FORENAME);
			String surname = r.get(T_PERSON.SURNAME);
			String campName = r.get(T_CAMP.NAME);
			String campPrice = r.get(T_CAMP.PRICE);
			LocalDateTime campArrive = r.get(T_CAMP.ARRIVE);
			String locationName = r.get(T_CAMP.NAME);
			BigDecimal paid = r.get(T_PERSON.PAID);
			BigDecimal requiredPrice = r.get(T_PERSON.REQUIRED_PRICE);
			list.add(new BusinessBean(fkPerson, forename, surname, campName, campPrice, campArrive, locationName, paid, requiredPrice));
		}
		return list;
	}

	/**
	 * update the database by changed records in the list
	 *
	 * @param list the list of beans
	 * @return the number of affected database rows
	 */
	public int updatePaid(List<BusinessBean> list) {
		Integer count = 0;
		for (BusinessBean bean : list) {
			if (bean.isChanged()) {
				UpdateConditionStep<TPersonRecord> sql = jooq
				// @formatter:off
					.update(T_PERSON)
					.set(T_PERSON.PAID, bean.getPaid())
					.where(T_PERSON.PK.eq(bean.getFkPerson()));
				// @formatter:on
				LOGGER.trace(sql);
				count += sql.execute();
			}
		}
		return count;
	}
}
