/*
 *  Copyright 2013-2050 Emmanuel BRUN (contact@amapj.fr)
 * 
 *  This file is part of AmapJ.
 *  
 *  AmapJ is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.

 *  AmapJ is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with AmapJ.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * 
 */
 package fr.amapj.service.services.edgenerator.excel;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import fr.amapj.common.CollectionUtils;
import fr.amapj.common.DateUtils;
import fr.amapj.common.FormatUtils;
import fr.amapj.model.engine.rdblink.RdbLink;
import fr.amapj.model.models.cotisation.EtatPaiementAdhesion;
import fr.amapj.model.models.cotisation.PeriodeCotisation;
import fr.amapj.model.models.cotisation.PeriodeCotisationUtilisateur;
import fr.amapj.model.models.fichierbase.EtatUtilisateur;
import fr.amapj.model.models.fichierbase.Utilisateur;
import fr.amapj.service.engine.generator.excel.AbstractExcelGenerator;
import fr.amapj.service.engine.generator.excel.ExcelFormat;
import fr.amapj.service.engine.generator.excel.ExcelGeneratorTool;


/**
 * Permet la generation d'un bilan de l'activité à venir des amapiens, 
 * pour déterminer les amapiens qu'il faudra passer en inactif 
 */
public class EGBilanActiviteAdherent extends AbstractExcelGenerator
{	

	@Override
	public void fillExcelFile(RdbLink em,ExcelGeneratorTool et)
	{
		// Détermination de la liste des périodes de cotisations 
		em.createQuery("select p from PeriodeCotisation p ORDER BY p.dateDebut ASC");
		List<PeriodeCotisation> ps = em.result().list(PeriodeCotisation.class);
		
		// Date pour la colonne lastDate1 : colonne avec le montant commandé après la dernière période de cotisation  
		Date lastDate1=null;
		if (ps.size()>0)
		{
			lastDate1 = DateUtils.addDays(ps.get(ps.size()-1).dateFin,1);
		}
		
		// Date pour la colonne lastDate2 : colonne avec le montant commandé après la date du jour 
		Date lastDate2 = DateUtils.getDateWithNoTime();
		
		//
		int nbCol = 3 + ps.size()*3+(lastDate1==null ? 0 : 1) + 1; 
		
		// 
		et.addSheet("Bilan", nbCol, 12);
		et.setColumnWidth(0, 20);
		et.setColumnWidth(1, 20);
		et.setColumnWidth(2, 40);

		
		// Construction de l'entete
		contructEntete(et,ps,lastDate1,lastDate2);
		
		// Récupération de la liste des utilisateurs actifs 
		em.createQuery("select u from Utilisateur u where u.etatUtilisateur=:etatUtilisateur ");
		em.setParameter("etatUtilisateur", EtatUtilisateur.ACTIF);
		List<Utilisateur> us = em.result().list(Utilisateur.class);
		CollectionUtils.collatorSort(us, e->e.nom,e->e.prenom);

		// Contruction d'une ligne pour chaque Utilisateur
		for (Utilisateur u : us)
		{
			contructRow(et,em,ps,u,lastDate1,lastDate2);
		}	
		
	}



	private void contructEntete(ExcelGeneratorTool et, List<PeriodeCotisation> ps,Date lastDate1,Date lastDate2)
	{
		SimpleDateFormat df1 = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
		
		// Ligne de titre
		et.addRow("Bilan de l'activité des adhérents. Réalisé le "+df1.format(DateUtils.getDate()),et.grasGaucheNonWrappe);
			
		// Ligne vide
		et.addRow();

		// Ligne de Nom Prenom Email ... 
		et.addRow();
		et.setCell(0, "Nom", et.grasGaucheNonWrappeBordure);
		et.setCell(1, "Prénom", et.grasGaucheNonWrappeBordure);
		et.setCell(2, "E mail", et.grasGaucheNonWrappeBordure);
		
		int index = 3;
		for (PeriodeCotisation p : ps) 
		{	
			et.setCell(index, ""+p.nom, et.grasCentreBordure);
			et.mergeCellsRight(index, 3);
			index=index+3;;
		}
		
		if (lastDate1!=null)
		{
			et.setCell(index, "Mnt commandé après le "+FormatUtils.getStdDate().format(lastDate1), et.grasCentreBordure);
			index++;
		}
		
		// 
		et.setCell(index, "Mnt commandé après le "+FormatUtils.getStdDate().format(lastDate2), et.grasCentreBordure);
		
		et.addRow();
		et.setRowHeigth(3);
		et.mergeCellsUp(0, 2);
		et.mergeCellsUp(1, 2);
		et.mergeCellsUp(2, 2);

		
		index = 3;
		for (PeriodeCotisation p : ps) 
		{	
			et.setCell(index, "Mnt commandé", et.grasCentreBordure);
			index++;
			et.setCell(index, "Adhésion réglée", et.grasCentreBordure);
			index++;
			et.setCell(index, "Mnt adhésion", et.grasCentreBordure);
			index++;
		}		
		
		if (lastDate1!=null)
		{
			et.mergeCellsUp(index, 2);
			index++;
		}
		et.mergeCellsUp(index, 2);
	}
	
	

	private void contructRow(ExcelGeneratorTool et, RdbLink em, List<PeriodeCotisation> ps, Utilisateur u, Date lastDate1,Date lastDate2) 
	{
		et.addRow();
		
		et.setCell(0, u.nom, et.grasGaucheNonWrappeBordure);
		et.setCell(1, u.prenom, et.nonGrasGaucheBordure);
		et.setCell(2, u.email, et.nonGrasGaucheBordure);
		
		
		int index = 3;
		for (PeriodeCotisation p : ps) 
		{
			AdhesionInfo info = getAdhesionInfo(em,p,u);
			
			et.setCellPrix(index, getMntCommande(em,u,p), et.prixCentreBordure);
			index++;
			et.setCell(index, info.isReglee ? "OUI" : "NON", et.switchColor(et.grasCentreBordure,info.isReglee ? 0 : 1));
			index++;
			et.setCellPrix(index, info.montant, et.switchColor(et.prixCentreBordure,info.isReglee ? 0 : 1));
			index++;
		}		
		
		if (lastDate1!=null)
		{
			et.setCellPrix(index, getMntCommandeAfter(em,u,lastDate1), et.prixCentreBordure);
			index++;
		}
		
		et.setCellPrix(index, getMntCommandeAfter(em,u,lastDate2), et.prixCentreBordure);
		
	}

	static public class AdhesionInfo
	{
		public boolean isReglee;
		public int montant;
	}
	
	private AdhesionInfo getAdhesionInfo(RdbLink em, PeriodeCotisation p, Utilisateur u) 
	{
		em.createQuery("select pu from PeriodeCotisationUtilisateur pu WHERE "+
						"pu.utilisateur=:u AND  "+
						"pu.periodeCotisation=:p");
		em.setParameter("u", u);
		em.setParameter("p", p);
		
		PeriodeCotisationUtilisateur pcu = em.result().oneOrZero(PeriodeCotisationUtilisateur.class);
		AdhesionInfo ret = new AdhesionInfo();
		
		if (pcu==null)
		{
			ret.isReglee = false;
			return ret;
		}
		
		ret.isReglee = pcu.etatPaiementAdhesion ==EtatPaiementAdhesion.ENCAISSE;
		ret.montant = pcu.montantAdhesion;
		return ret;
		
	}

	private int getMntCommande(RdbLink em, Utilisateur u, PeriodeCotisation p) 
	{
		em.createQuery("select sum(a.qte*a.modeleContratProduit.prix) from ContratCell a where "
				+ "a.contrat.utilisateur = :u AND "
				+ "a.modeleContratDate.dateLiv >= :dateDebut AND "
				+ "a.modeleContratDate.dateLiv <= :dateFin");

		em.setParameter("u",u);
		em.setParameter("dateDebut", p.dateDebut);
		em.setParameter("dateFin", p.dateFin);

		return em.result().singleInt();
	}

	private int getMntCommandeAfter(RdbLink em, Utilisateur u, Date lastDate) 
	{
		em.createQuery("select sum(a.qte*a.modeleContratProduit.prix) from ContratCell a where "
				+ "a.contrat.utilisateur = :u AND "
				+ "a.modeleContratDate.dateLiv >= :dateDebut");

		em.setParameter("u",u);
		em.setParameter("dateDebut", lastDate);

		return em.result().singleInt();

	}


	@Override
	public String getFileName(RdbLink em)
	{
		return "bilan-activite-adherents";
	}
	

	@Override
	public String getNameToDisplay(RdbLink em)
	{
		return "Bilan de l'activité par adhérent";
	}
	
	@Override
	public ExcelFormat getFormat()
	{
		return ExcelFormat.XLS;
	}
}
