package Models;

import Controllers.Stock.ListProduitBon;
import Controllers.Traitement.Adaptateur;
import static Controllers.Traitement.Adaptateur.DatabaseDateLocalDate;
import static Controllers.Traitement.Adaptateur.StringToLocalDate;
import Controllers.Traitement.ParametreSystem;
import Models.BonLivraisonClt.BonLivraisonClt;
import Models.BonLivraisonClt.BonLivraisonCltDB;
import Models.Caisse.CarteBancaireClt;
import Models.ChequeClt.ChequeClt;
import Models.ChequeClt.ChequeList;
import Models.Client.Client;
import Models.Client.ClientDB;
import Models.Client.ClientEntreprise;
import Models.Client.ClientEntrepriseDB;
import Models.CommandeClt.CommandeClt;
import Models.CommandeClt.CommandeCltDB;
import Models.DevisClt.Devis;
import Models.DevisClt.DevisDB;
import Models.FactureClt.FactureClt;
import Models.FactureClt.FactureCltDB;
import Models.Produit.ListeProduit;
import Models.Produit.Produit;
import Models.Produit.ProduitDB;
import Models.Stock.BonEntree;
import Models.Stock.BondeEntrerDB;
import Models.TraiteClt.TraiteClt;
import Models.TraiteClt.TraiteList;
import Models.User.User;
import java.sql.Time;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

/**
 * @author Maher Ben Tili
 */
public class SimpleDataVente {

    ObservableList<Produit>  Produits = null;
    
    ObservableList<ClientEntreprise> ClientEntreprises = null;
    ObservableList<Client> Clients = null;
    ObservableList<String> Transporteurs = null;
    ObservableList<String> Magasins = null;
    ObservableList<String> Banques = null;
    
    public SimpleDataVente() 
    {
        Produits = new ProduitDB().getAllProduits();
        ClientEntreprises = new ClientEntrepriseDB().getAllCltEntreprise();
        Clients = new ClientDB().getAllClient();
        Transporteurs = FXCollections.observableArrayList("Mabrouk Gillot", "Manoubi Dewet", "Salah Dubuisson", "Ali Romann", "Sabir Kariger");
        Magasins = FXCollections.observableArrayList("Magasin II", "Magasin III", "Magasin IV");
        Banques = FXCollections.observableArrayList("STB", "BNA", "BH", "BFPME", "BTS", "BTE", "BTL", "TSB", "ATB","ABC", "BIAT", "BT", "Amen Bank", "AttijariBank");
    }
    
    
    public void setDataBonEnter(int nbrBonEnter)
    {
        int[] uniqueArray = Adaptateur.generateUniqueRandomArray(nbrBonEnter, 10000); 
        
        for(int i=0; i<nbrBonEnter; i++)
        {
            BonEntree BonEntre = new BonEntree();
            
            BonEntre.setId(String.valueOf(uniqueArray[i]));

            BonEntre.setLocal_recepteur(ParametreSystem.NomLocalPC);
            BonEntre.setLocal_emetteur(Adaptateur.getRandomObject(Magasins));

            BonEntre.setTransporteur(Adaptateur.getRandomObject(Transporteurs));
            
            LocalDate date = Adaptateur.getRandomDateBetween(LocalDate.of(2022, 1, 1), LocalDate.of(2025, 12, 31));
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            String formattedDate = date.format(formatter);
            BonEntre.setDate(formattedDate);

            Time time = new Time(Adaptateur.getRandomValueBetween(10, 17), Adaptateur.getRandomValueBetween(0, 59), 00);
            BonEntre.setHeur(time);

            List<Produit> randomProduits = Adaptateur.getUniqueRandomObjectList(Produits, Adaptateur.getRandomValueBetween(2, 25) );
            ObservableList<ListProduitBon> ListProduitBons = getListProduitBons(randomProduits);

            new BondeEntrerDB().addBonEntrer(BonEntre, ListProduitBons);
        }
    }
    
    public void setDataFactureClt(int nbrFacture)
    {
        FactureClt Facture = new FactureClt();
        
        ObservableList<CommandeClt> commandes = new CommandeCltDB().getAllCommandesClt();
        for(int i=0; i<commandes.size(); i++)
        {
            CommandeClt randomCommande = commandes.get(i);

            Facture.setIdCommandeClt(randomCommande.getCodecommandeclt());

            Facture.setIdBonLivraisonClt(randomCommande.getCodeBonLivraison());

            Facture.setListeproduit(randomCommande.getListeproduit());

            Facture.setNetAPayer(randomCommande.getNetAPayer());
            Facture.setTotalTVA(randomCommande.getTotalTVA());
            Facture.setTotalHorsTaxNet(randomCommande.getTotalHorsTaxNet());
            Facture.setRemise(randomCommande.getRemise());

            LocalDate LocalDateCommande = StringToLocalDate(randomCommande.getDate());
            LocalDate LocalDateCreation = LocalDateCommande.plusWeeks(Adaptateur.getRandomValueBetween(6, 8));
            //String heure = Adaptateur.getRandomTimeBetween(LocalTime.of(8, 0), LocalTime.of(18, 0));
            Facture.setDateFacture(DatabaseDateLocalDate(LocalDateCreation));
            
            String TypeRegement = randomCommande.getTypeRegement();
            Facture.setTypeRegement(TypeRegement); 

            int TypeClient = randomCommande.getTypeClient();
            String NomClient = "";
            Facture.setTypeClient(TypeClient);
            if(TypeClient == 0){
                Facture.setCltPersonne(randomCommande.getCltPersonne());
                NomClient = randomCommande.getCltPersonne().getNomcomplet();
            }else if(randomCommande.getTypeClient() == 1){
                Facture.setCltEntreprise(randomCommande.getCltEntreprise());
                NomClient = randomCommande.getCltEntreprise().getNom();
            }


            //0 Comptent
            if(TypeRegement.equals("0")){
                int ModePaiement = Adaptateur.getRandomValueBetween(0, 3);
                Facture.setModePaiement(String.valueOf(ModePaiement));
                if(ModePaiement == 1){
                    ChequeClt Cheque = new ChequeClt();
                    Cheque.setBanqueChequeClt(Adaptateur.getRandomObject(Banques));
                    Cheque.setNumeroChequeClt(String.valueOf(Adaptateur.getRandomValueBetween(1, 500)));
                    Cheque.setNomCompletChequeClt(NomClient);
                    Cheque.setDatePaiement(DatabaseDateLocalDate(LocalDateCreation));
                    Cheque.setMontantChequeClt(Facture.getNetAPayer());
                    Facture.setCheque(Cheque);
                }else if(ModePaiement == 2){
                    CarteBancaireClt CarteBancaire =  new CarteBancaireClt();
                    CarteBancaire.setNumeroTransation(String.valueOf(Adaptateur.getRandomValueBetween(5000, 50000)));
                    CarteBancaire.setNomBanque(Adaptateur.getRandomObject(Banques));
                    CarteBancaire.setNumeroCarte(String.valueOf(Adaptateur.getRandomValueBetween(50000, 90000)));
                    CarteBancaire.setNomComplet(NomClient);
                    CarteBancaire.setMontant(Facture.getNetAPayer());
                    CarteBancaire.setLocalNom(ParametreSystem.NomLocalPC);
                    CarteBancaire.setIdProfile(User.idprofile);
                    Facture.setCarteBancaire(CarteBancaire);
                }
            }
            else if(TypeRegement.equals("1")){
                float NetaPayer = Adaptateur.StringToFloat(Facture.getNetAPayer());
                int NbrTraite = Adaptateur.getRandomValueBetween(3, 6);
                float TauxIntere = (float) 2.5;
                int Avance = Math.round(NetaPayer / 3);
                
                float MontantInteret = ((NetaPayer - Avance) * TauxIntere) / 100 ;
                float TotalMontantTraite = (NetaPayer - Avance) + MontantInteret ; 
        
                Integer divTotal = Adaptateur.Diviseur(TotalMontantTraite);
                float modeTotal = Adaptateur.Modulo(TotalMontantTraite);

                float Value = (float) TotalMontantTraite / NbrTraite;
                Integer div = Adaptateur.Diviseur(Value);

                java.util.Date date = Date.from(LocalDateCreation.atStartOfDay(ZoneId.systemDefault()).toInstant());
                //java.util.Date date= new java.util.Date();
                Calendar cal = Calendar.getInstance();

                Integer  Somme = 0;
                
                Facture.setAvance(Adaptateur.ArrondFloatToStringOrigin(Avance));
                Facture.setTotalMontantTraite(Adaptateur.ArrondFloatToString(TotalMontantTraite));
                Facture.setNbrTraite(Adaptateur.ArrondFloatToStringOrigin(NbrTraite));
                Facture.setMontantInteret(Adaptateur.ArrondFloatToString(MontantInteret));
                Facture.setTauxInteret(Adaptateur.ArrondFloatToStringOrigin(TauxIntere));
        
                //0 Traite | 1 Cheque
                String TypeFacilite = String.valueOf(Adaptateur.getRandomValueBetween(0, 1));
                Facture.setTypeFacilite(TypeFacilite);
                if(TypeFacilite.equals("0"))
                {
                    ObservableList<TraiteList> dataList = FXCollections.observableArrayList();
                    for(int t=0; t<NbrTraite; t++){
                        cal.setTime(date);
                        cal.add(Calendar.MONTH, t+1);
                        if(t != NbrTraite-1){
                            Somme = Somme + div ;
                            dataList.add(new TraiteList(Adaptateur.floatDeleZero(div),  cal.getTime()));
                        }else{
                            dataList.add(new TraiteList(Adaptateur.floatDeleZero((divTotal - Somme) + modeTotal) ,  cal.getTime()));
                        }
                    }
                    ArrayList<TraiteClt> ListTraites = new ArrayList();
                    for(int t1=0; t1<dataList.size(); t1++){
                        TraiteClt Traite = new TraiteClt();
                        Traite.setDateCreationTraiteClt(new java.util.Date().toString());
                        String DateTraite = new SimpleDateFormat("dd/MM/yyyy").format(dataList.get(t1).getDate());
                        Traite.setDateTraiteClt(DateTraite);
                        Traite.setMontantTraiteClt(dataList.get(t1).getMontantTraite());
                        ListTraites.add(Traite);
                    }
                    Facture.setListeTraites(ListTraites);
                    
                }else if(TypeFacilite.equals("1"))
                {
                    ObservableList<ChequeList> dataListCheque = FXCollections.observableArrayList();
                    int NumeroCheque = Adaptateur.getRandomValueBetween(10, 300);
                    String BanqueCheque = Adaptateur.getRandomObject(Banques);
                    
                    for(int c=0; c<NbrTraite; c++){
                        cal.setTime(date);
                        cal.add(Calendar.MONTH, c+1);
                        if(c != NbrTraite-1){
                            Somme = Somme + div ;
                            dataListCheque.add(new ChequeList(cal.getTime(), String.valueOf(NumeroCheque + c), BanqueCheque, Adaptateur.floatDeleZero(div)));
                        }else{
                            dataListCheque.add(new ChequeList(cal.getTime(), String.valueOf(NumeroCheque + c), BanqueCheque, Adaptateur.floatDeleZero((divTotal - Somme) + modeTotal)));
                        }
                    }
                    ArrayList<ChequeClt> ListCheque = new ArrayList();
                    for(int c1=0; c1<dataListCheque.size(); c1++){
                        ChequeClt Cheque = new ChequeClt();
                        Cheque.setNumeroChequeClt(dataListCheque.get(c1).getNumeroCheque());
                        Cheque.setBanqueChequeClt(dataListCheque.get(c1).getBanqueCheque());
                        Cheque.setMontantChequeClt(dataListCheque.get(c1).getMontantCheque());
                        String DateChequePaiement = new SimpleDateFormat("yyyy-MM-dd").format(dataListCheque.get(c1).getDate());
                        Cheque.setDatePaiement(DateChequePaiement);
                        Cheque.setDateCreation(new java.util.Date().toString());
                        ListCheque.add(Cheque);
                    }
                    Facture.setListeCheques(ListCheque);
                }
            }
            String CodeFacture = new FactureCltDB().AddFactureClt(Facture);
        }
        
    }
    
    public void setDataBonLivraisonClt(int nbrBonLivraison)
    {
        ObservableList<CommandeClt> commandes = new CommandeCltDB().getAllCommandesClt();
        
        
        for(int i=0; i<nbrBonLivraison; i++)
        {
            BonLivraisonClt BonLivraison = new BonLivraisonClt();
            
            BonLivraison.setTransporteur(Adaptateur.getRandomObject(Transporteurs));
            
            CommandeClt randomCommande = Adaptateur.getRandomObject(commandes);
            BonLivraison.setIdCommande(randomCommande.getCodecommandeclt());

            BonLivraison.setTypeClient(randomCommande.getTypeClient());
            if(randomCommande.getTypeClient() == 0){
                BonLivraison.setCltPersonne(randomCommande.getCltPersonne());
                BonLivraison.setAdresseLivraison(randomCommande.getCltPersonne().getAdresse());
            }else if(randomCommande.getTypeClient() == 1){
                BonLivraison.setCltEntreprise(randomCommande.getCltEntreprise());
                BonLivraison.setAdresseLivraison(randomCommande.getCltEntreprise().getAdresse());
            }

            BonLivraison.setListeproduit(randomCommande.getListeproduit());
            BonLivraison.setTotalHorsTaxNet(randomCommande.getTotalHorsTaxNet());
            BonLivraison.setTotalTVA(randomCommande.getTotalTVA());
            BonLivraison.setRemise(randomCommande.getRemise());
            BonLivraison.setNetAPayer(randomCommande.getNetAPayer());

            String heure = Adaptateur.getRandomTimeBetween(LocalTime.of(8, 0), LocalTime.of(18, 0));
            BonLivraison.setHeurLivraison(heure);

            LocalDate LocalDateCommande = StringToLocalDate(randomCommande.getDate());
            LocalDate LocalDateCreation = LocalDateCommande.plusWeeks(Adaptateur.getRandomValueBetween(1, 5));
            BonLivraison.setDateCreation(DatabaseDateLocalDate(LocalDateCreation));

            LocalDate LocalDateLivraison = LocalDateCreation.plusWeeks(1);
            BonLivraison.setDateLivraisonPreveu(DatabaseDateLocalDate(LocalDateLivraison));

            BonLivraison.setFrais(String.valueOf(Adaptateur.getRandomValueBetween(0, 50)));

            BonLivraison.setPoidProduit(String.valueOf(Adaptateur.getRandomValueBetween(0, 25)));

            BonLivraison.setTele1(String.valueOf(Adaptateur.getRandomValueBetween(23000000, 23999999)));        

            BonLivraison.setTele2(String.valueOf(Adaptateur.getRandomValueBetween(52000000, 52999999)));

            String CodeBonLivraison = new BonLivraisonCltDB().AddBonLivraisonClt(BonLivraison);
            
            new CommandeCltDB().UpdateCommandeCltSetIdBonLivraison(BonLivraison.getIdCommande(), CodeBonLivraison);
        }
    }
    
    public void setDataCommandeClt(int nbrCommande)
    {
        for(int i=0; i<nbrCommande; i++)
        {
            CommandeClt commandeclt = new CommandeClt();

            int importDevis = Adaptateur.getRandomValueBetween(0, 1);
            if(importDevis == 0)
            {
                LocalDate date = Adaptateur.getRandomDateBetween(LocalDate.of(2022, 1, 1), LocalDate.of(2025, 12, 31));
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                String formattedDate = date.format(formatter);
                commandeclt.setDate(formattedDate);
                
                List<Produit> randomProduits = Adaptateur.getUniqueRandomObjectList(Produits, Adaptateur.getRandomValueBetween(2, 10) );
                ObservableList<ListeProduit> listeProduit = getListProduits(randomProduits);
                commandeclt.setListeproduit(listeProduit);

                int TypeClient = Adaptateur.getRandomValueBetween(0, 1);
                commandeclt.setTypeClient(TypeClient);
                if(TypeClient == 0){
                    Client randomClient = Adaptateur.getRandomObject(Clients);
                    commandeclt.setCltPersonne(randomClient);
                }else if(TypeClient == 1){
                    ClientEntreprise randomEntreprise = Adaptateur.getRandomObject(ClientEntreprises);
                    commandeclt.setCltEntreprise(randomEntreprise);
                }
                commandeclt.setTypeRegement(String.valueOf(Adaptateur.getRandomValueBetween(0, 1)));

                Map<String, Float>  map = CalculeTotalProduits(listeProduit);
                commandeclt.setNetAPayer(map.get("NetaPayer").toString());
                commandeclt.setTotalTVA(map.get("TotalTVA").toString());
                commandeclt.setTotalHorsTaxNet(map.get("Total_H_T_Net").toString());
                commandeclt.setRemise(map.get("Remise").toString());
            }else if(importDevis == 1){
                ObservableList<Devis> ListAllDevis = new DevisDB().getAllDevis();
                Devis randomDevis = Adaptateur.getRandomObject(ListAllDevis);

                commandeclt.setCodeDevis(randomDevis.getCodeDevis());
                commandeclt.setDate(randomDevis.getDateCreation());
                commandeclt.setListeproduit(randomDevis.getListeproduit());

                commandeclt.setTypeClient(randomDevis.getTypeClient());
                if(randomDevis.getTypeClient() == 0){
                    commandeclt.setCltPersonne(randomDevis.getClient());
                }else if(randomDevis.getTypeClient() == 1){
                    commandeclt.setCltEntreprise(randomDevis.getEntreprise());
                }
                commandeclt.setTypeRegement(randomDevis.getTypeRegement());
                commandeclt.setNetAPayer(randomDevis.getNetAPayer());
                commandeclt.setTotalTVA(randomDevis.getTotalTVA());
                commandeclt.setTotalHorsTaxNet(randomDevis.getTotalHorsTaxNet());
                commandeclt.setRemise(randomDevis.getRemise());
            }
            new CommandeCltDB().AddCommandeClt(commandeclt);
        }
    }
    
    
    public void setDataDevisClt(int nbrDevis)
    {
        for(int i=0; i<nbrDevis; i++)
        {
            Devis devis = new Devis();

            List<Produit> randomProduits = Adaptateur.getUniqueRandomObjectList(Produits, Adaptateur.getRandomValueBetween(2, 10) );
            ObservableList<ListeProduit> listeProduit = getListProduits(randomProduits);
            devis.setListeproduit(listeProduit);

            LocalDate date = Adaptateur.getRandomDateBetween(LocalDate.of(2022, 1, 1), LocalDate.of(2025, 12, 31));
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
            String formattedDate = date.format(formatter);
            devis.setDateCreation(formattedDate);        

            int TypeClient = Adaptateur.getRandomValueBetween(0, 1);
            devis.setTypeClient(TypeClient);
            if(TypeClient == 0){
                Client randomClient = Adaptateur.getRandomObject(Clients);
                devis.setClient(randomClient);
                devis.setCodeClient(randomClient.getCodeclient());
            }else if(TypeClient == 1){
                ClientEntreprise randomEntreprise = Adaptateur.getRandomObject(ClientEntreprises);
                devis.setEntreprise(randomEntreprise);
                devis.setCodeClient(randomEntreprise.getCodeString());
            }

            String dateFinValidite = date.plusMonths(1).format(formatter);
            devis.setValidite(dateFinValidite);

            Map<String, Float>  map = CalculeTotalProduits(listeProduit);
            devis.setNetAPayer(map.get("NetaPayer").toString());
            devis.setTotalTVA(map.get("TotalTVA").toString());
            devis.setTotalHorsTaxNet(map.get("Total_H_T_Net").toString());
            devis.setRemise(map.get("Remise").toString());

            devis.setTypeRegement(String.valueOf(Adaptateur.getRandomValueBetween(0, 1)));

            new DevisDB().AddDevis(devis);
        }
    }
    
    
    
    
    
    private ObservableList<ListeProduit> getListProduits(List<Produit> listProduits)
    {   
        ObservableList<ListeProduit> ListProduit = FXCollections.observableArrayList();
        for(Produit prod : listProduits){
            float prixht = Adaptateur.StringToFloat(prod.getPrixventeht()) ;
            float tva = Adaptateur.StringToFloat(prod.getTvavente());
            float qte = (float) Adaptateur.getRandomValueBetween(1, 7);
            float remise = (float) Adaptateur.getRandomValueBetween(1, 30) ;
            float totalht = (prixht - ((prixht * remise)/100))* qte ;
            float totalttc = totalht + ((totalht * tva)/100) ;
            
            ListProduit.add(new ListeProduit(prod.getReference(), prod.getDesignation(), Adaptateur.floatDeleZero(qte), prod.getPrixventeht(), Adaptateur.floatDeleZero(remise), Adaptateur.floatDeleZero(totalht), prod.getTvavente(), Adaptateur.floatDeleZero(totalttc)));
        }
        return ListProduit;
    }
    
    private ObservableList<ListProduitBon> getListProduitBons(List<Produit> listProduits)
    {   
        ObservableList<ListProduitBon> ListProduitBons = FXCollections.observableArrayList();
        for(Produit prod : listProduits){
            float prixht = Adaptateur.StringToFloat(prod.getPrixventeht()) ;
            float tva = Adaptateur.StringToFloat(prod.getTvavente());
            float qte = (float) Adaptateur.getRandomValueBetween(1, 7);
            float remise = (float) Adaptateur.getRandomValueBetween(1, 30) ;
            float totalht = (prixht - ((prixht * remise)/100))* qte ;
            float totalttc = totalht + ((totalht * tva)/100) ;
            
            ListProduitBons.add(new ListProduitBon(prod.getReference(), prod.getDesignation(), prod.getMarque(), prod.getCategorie(), Adaptateur.floatDeleZero(totalttc), Adaptateur.floatDeleZero(qte), prod.getTvavente()));
        }
        return ListProduitBons;
    }
    
    private Map<String, Float> CalculeTotalProduits(ObservableList<ListeProduit> listProduits)
    {   
        float  NetaPayer = 0;
        float  Remise = 0;
        float  TotalTVA = 0;
        float  Total_H_T_Net= 0;
        
        //calcule
        for(ListeProduit liste : listProduits){
            float totaht = Adaptateur.StringToFloat(liste.getTotalHT()) ;
            float prix_U_H_T = Adaptateur.StringToFloat(liste.getPrixHT()) ;
            float remise = Adaptateur.StringToFloat(liste.getRemise().replace("%", "")) ;
            float tva = Adaptateur.StringToFloat(liste.getTVA().replace("%", ""));
           
            TotalTVA = TotalTVA + ((totaht *  tva) /100) ;
            
            Remise =  Remise + (prix_U_H_T * remise)/100 ;
            
            Total_H_T_Net = Total_H_T_Net + totaht ;
        }

        if(Total_H_T_Net>0){
            float timbre = Adaptateur.StringToFloat(ParametreSystem.Timbre);
            NetaPayer = Total_H_T_Net + TotalTVA + timbre ;
        }
        
        Map<String, Float> map = new HashMap<>();
        map.put("NetaPayer", NetaPayer);
        map.put("Remise", Remise);
        map.put("TotalTVA", TotalTVA);
        map.put("Total_H_T_Net", Total_H_T_Net);
        
        return map;
    }    
}
