using System.Collections.Generic;
using System.Web.Services;
using Consulenza.Unica.Business;
using Consulenza.WebTemplateModeler.Entity;
using Consulenza.ReportArchive.Entity;
using Consulenza.ReportWriter.Manager.Section.Entity;
using Consulenza.ReportWriter.Business.Entity;

using System;
using Consulenza.ReportCommon;
using System.Linq;
using Newtonsoft.Json;


namespace Consulenza.Unica.Services
{
    /// <summary>
    /// Summary description for ReportManager
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    public class ReportManager : WebService
    {

        //test prova git
        [WebMethod(MessageName = "CreaReportPO")]
        public byte[] CreaReportPO(string codiceAgente, string codiceFiscale, string codiceMandato, string codiceRete, long chiaveProposta)
        {    
            var mt = new WebTemplateModelerService();
            Template template = mt.GetTemplate(codiceRete.Equals("S") ? 10000 :9000, "S");
            return CreaReport(codiceAgente, codiceFiscale, codiceMandato, codiceRete, chiaveProposta, template,new List<Parametro>());                        
        }



        [WebMethod(MessageName = "CreaReportNoChiave")]
        public byte[] CreaReportNoChiave(string codiceAgente, string codiceFiscale, string codiceMandato, string codiceRete, Template template, List<Parametro> parametri)
        {
            List<DateTime> dateTime = new List<DateTime>();
            dateTime.Add(DateTime.Now);

            var mt = new WebTemplateModelerService();
            byte[] reportByte= new byte[0];
            Consulenza.DataServices.DatiSeiUnico datiSeiUnico = null;
            ReportStruct strutturaReport = null;
            Modello modello = null;
            GeneratorService generatorService = null;
            string metodo = "";            

            try {
               
                metodo += " codiceAgente=" + codiceAgente + " codiceFiscale=" + codiceFiscale + " codiceMandato=" + codiceMandato + " codiceRete=" + codiceRete;
                template = mt.TestTemplate(template, metodo);              
                modello = mt.GetModello(template.IdModello);
            } catch (Exception ex) {  
                mt.insertLog("", "", "", "", "Caricamento Modello/Template " + metodo, ex);
                throw new Exception("Caricamento Modello/Template " + metodo + " " + ex.Message);
            }

           
            
            try{
                strutturaReport = new ReportStruct  {
                    Opzioni = template.Options.Distinct().ToDictionary(x => x.Key, x => x.Value),
                    Schede = (from schede in template.Schede 
                              join modelli in modello.Schede
                                  on schede.Id equals modelli.Id
                                where modelli.Sezioni !="0"
                              select new ReportCommon.Scheda
                              {
                                  Id = Convert.ToInt32(modelli.Sezioni),
                                  Opzioni = schede.Options.Distinct().ToDictionary(x => x.Key, x => x.Value)
                              }).ToList()
                };

                var Opzione10 = (from o in template.Options where o.Key == "Opzione10" select o.Value).LastOrDefault();
                if(Opzione10!=null){
                    foreach (int s in  JsonConvert.DeserializeObject<Opzione10>(Opzione10).idSchede) {
                        strutturaReport.Schede.Add(new ReportCommon.Scheda
                        {
                            Id = s,
                            Opzioni = new Dictionary<string,string>()
                        });
                    }
                }

               
                foreach (var scheda in strutturaReport.Schede)    {
                    if (strutturaReport.Opzioni.ContainsKey("Opzione1"))
                        scheda.Opzioni.Add("Opzione1", strutturaReport.Opzioni["Opzione1"]); 

                    if (strutturaReport.Opzioni.ContainsKey("Opzione2"))
                        scheda.Opzioni.Add("Opzione2", strutturaReport.Opzioni["Opzione2"]); 
                }            
            } catch (Exception ex) { 
                mt.insertLog(modello.Id.ToString(),template.CodicePb, template.Id.ToString(),template.IsDefault, "strutturaReport " + metodo, ex);
                throw new Exception("strutturaReport " + metodo + " " + ex.Message);
            }

            

            try {

                datiSeiUnico = new Consulenza.DataServices.DatiSeiUnico(
                   codiceAgente,
                   codiceFiscale,
                   codiceMandato,
                   codiceRete,
                   0,
                   0,
                   (from s in template.Schede select s.Id).ToList<int>()
                );
                dateTime.Add(DateTime.Now);
                datiSeiUnico.Execute();
                dateTime.Add(DateTime.Now);
                generatorService = new GeneratorService(datiSeiUnico);
             
             } catch (Exception ex) {
                 mt.insertLog(modello.Id.ToString(), template.CodicePb, template.Id.ToString(), template.IsDefault, datiSeiUnico.UrlFideuramDati + " " + metodo, ex);
                 throw new Exception(datiSeiUnico.UrlFideuramDati + " " + metodo + " " + ex.Message);
             }

            

             try {
               
                switch (modello.Nome.ToLower())
                {
                    case "diagnosi":
                      
                        reportByte = generatorService.CreaReport_Diagnosi(strutturaReport);
                        break;
                    case "monitoraggio":
                      
                        reportByte = generatorService.CreaReport_Monitoraggio(strutturaReport);
                        break;
                    case "proposta":
                     
                        reportByte = generatorService.CreaReport_Proposta(strutturaReport);
                        break;
                    case "nucleo":
                       
                        reportByte = generatorService.CreaReport_Nucleo(strutturaReport);
                        break;
                    default:
                        throw new Exception("CreaReport_" + modello.Nome.ToLower() + " non esistente");
                  
                }
            }
            catch (Exception ex) {
                mt.insertLog(modello.Id.ToString(), template.CodicePb, template.Id.ToString(), template.IsDefault, "CreaReport_" + modello.Nome + " " + metodo, ex);
                throw new Exception("CreaReport_" + modello.Nome + " " + metodo + " " + ex.Message + " " + ex.StackTrace);
            }
            
            dateTime.Add(DateTime.Now);


           
            mt.insertLog(modello.Id.ToString(), template.CodicePb, template.Id.ToString(), template.IsDefault, "LogDate", metodo, dateTime);
            return reportByte;
        }

        [WebMethod(MessageName = "CreaReport")]
        public byte[] CreaReport(string codiceAgente, string codiceFiscale, string codiceMandato, string codiceRete, long chiave, Template template, List<Parametro> parametri)
        {
            List<DateTime> dateTime = new List<DateTime>();
            dateTime.Add(DateTime.Now);
            
            var mt = new WebTemplateModelerService();
            byte[] reportByte = new byte[0];
            Consulenza.DataServices.DatiSeiUnico datiSeiUnico = null;
            ReportStruct strutturaReport = null;
            Modello modello = null;
            GeneratorService generatorService = null;
            string metodo = "";
            string codiceFiscaleDelegato="";
            bool dettaglioProdotti = false;
            bool dettaglioProdottiCointestati = false;
            bool dettaglioProdottiTCM = false;
            VisualizzazioneProdotti visualizzazioneScelta =VisualizzazioneProdotti.PosizioniAttive;

            try
            {

                metodo += " codiceAgente=" + codiceAgente + " codiceFiscale=" + codiceFiscale + " codiceMandato=" + codiceMandato + " codiceRete=" + codiceRete + " chiave=" + chiave.ToString();
                template = mt.TestTemplate(template, metodo);
                modello = mt.GetModello(template.IdModello);
            }
            catch (Exception ex)
            {
                mt.insertLog("", "", "", "", "Caricamento Modello/Template " + metodo, ex);
                throw new Exception("Caricamento Modello/Template " + metodo + " " + ex.Message);
            }

            


            try
            {
                strutturaReport = new ReportStruct
                {
                    Opzioni = template.Options.Distinct().ToDictionary(x => x.Key, x => x.Value),
                    Schede = (from schede in template.Schede
                              join modelli in modello.Schede
                                  on schede.Id equals modelli.Id
                              where modelli.Sezioni != "0"
                              select new ReportCommon.Scheda
                              {
                                  Id = Convert.ToInt32(modelli.Sezioni),
                                  Opzioni = schede.Options.Distinct().ToDictionary(x => x.Key, x => x.Value)
                              }).ToList()
                };

                var Opzione10 = (from o in template.Options where o.Key == "Opzione10" select o.Value).LastOrDefault();
                if (Opzione10 != null)
                {
                    foreach (int s in JsonConvert.DeserializeObject<Opzione10>(Opzione10).idSchede)
                    {
                        strutturaReport.Schede.Add(new ReportCommon.Scheda
                        {
                            Id = s,
                            Opzioni = new Dictionary<string, string>()
                        });
                    }
                }
  


                foreach (var scheda in strutturaReport.Schede)
                {
                    if (strutturaReport.Opzioni.ContainsKey("Opzione1"))
                        scheda.Opzioni.Add("Opzione1", strutturaReport.Opzioni["Opzione1"]);

                    if (strutturaReport.Opzioni.ContainsKey("Opzione2"))
                        scheda.Opzioni.Add("Opzione2", strutturaReport.Opzioni["Opzione2"]);
                    foreach (var opzione in scheda.Opzioni)
                    {
                    if (opzione.Key == "Opzione5_3")
                        {                      
                            codiceFiscaleDelegato = JsonConvert.DeserializeObject<Opzione5_3>(opzione.Value).Valore;
                        }
                    // isSezione 55 equivale alla scheda 12 -- arriva dal DB
                        if (scheda.Id == 55)
                        {
                            if (opzione.Key == "Opzione4_1")
                            {
                                if (JsonConvert.DeserializeObject<Opzione4_1>(opzione.Value).Valore)
                                {
                                    dettaglioProdotti = true;
                                }
                            }
                            if (opzione.Key == "Opzione4_2")
                            {
                                if (JsonConvert.DeserializeObject<Opzione4_2>(opzione.Value).Valore)
                                {
                                    dettaglioProdottiCointestati = true;
                                }
                            }
                            if (opzione.Key == "Opzione4_3")
                            {
                                if (JsonConvert.DeserializeObject<Opzione4_3>(opzione.Value).Valore)
                                {
                                    dettaglioProdottiTCM = true;
                                }
                            }
                            if (opzione.Key == "Opzione12")
                            {
                                var paramList = JsonConvert.DeserializeObject<Opzione12>(opzione.Value).Valore.Split(',');
                                string paramVisualizzazione = paramList[paramList.Length-1];
                                switch (paramVisualizzazione)
                                {
                                    case "A":
                                        visualizzazioneScelta= VisualizzazioneProdotti.PosizioniAttive;
                                        break;
                                    case "SL":
                                        visualizzazioneScelta = VisualizzazioneProdotti.PosizioniLiquidate;
                                        break;
                                    case "CL":
                                        visualizzazioneScelta = VisualizzazioneProdotti.ContrattiLiquidati;
                                        break;
                                    default:
                                        visualizzazioneScelta = VisualizzazioneProdotti.All;
                                        break;
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                mt.insertLog(modello.Id.ToString(), template.CodicePb, template.Id.ToString(), template.IsDefault, "strutturaReport " + metodo, ex);
                throw new Exception("strutturaReport " + metodo + " " + ex.Message);
            }



            try
            {


             
                    datiSeiUnico = new Consulenza.DataServices.DatiSeiUnico(
                  codiceAgente,
                  codiceFiscale,
                  codiceMandato,
                  codiceRete,
                  !modello.Nome.ToLower().Equals("proposta") ? 0 : chiave,
                  !modello.Nome.ToLower().Equals("nucleo") ? 0 : chiave,
                  (from s in template.Schede select s.Id).ToList<int>(),
                  codiceFiscaleDelegato,
                  dettaglioProdotti, dettaglioProdottiCointestati, visualizzazioneScelta, dettaglioProdottiTCM
                 );
                


                dateTime.Add(DateTime.Now);
                datiSeiUnico.Execute();
                 dateTime.Add(DateTime.Now);
                generatorService = new GeneratorService(datiSeiUnico);

            }
            catch (Exception ex)
            {
                mt.insertLog(modello.Id.ToString(), template.CodicePb, template.Id.ToString(), template.IsDefault, datiSeiUnico.UrlFideuramDati + " " + metodo, ex);
                throw new Exception(datiSeiUnico.UrlFideuramDati + " " + metodo + " " + ex.Message);
            }



            try
            {

                switch (modello.Nome.ToLower())
                {
                    case "diagnosi":

                        reportByte = generatorService.CreaReport_Diagnosi(strutturaReport);
                        break;
                    case "monitoraggio":

                        reportByte = generatorService.CreaReport_Monitoraggio(strutturaReport);
                        break;
                    case "proposta":

                        reportByte = generatorService.CreaReport_Proposta(strutturaReport);
                        break;
                    case "nucleo":

                        reportByte = generatorService.CreaReport_Nucleo(strutturaReport);
                        break;
                    default:
                        throw new Exception("CreaReport_" + modello.Nome.ToLower() + " non esistente");

                }
            }
            catch (Exception ex)
            {
                mt.insertLog(modello.Id.ToString(), template.CodicePb, template.Id.ToString(), template.IsDefault, "CreaReport_" + modello.Nome + " " + metodo, ex);
                throw new Exception("CreaReport_" + modello.Nome + " " + metodo + " " + ex.Message + " " + ex.StackTrace);
            }

            dateTime.Add(DateTime.Now);



            mt.insertLog(modello.Id.ToString(), template.CodicePb, template.Id.ToString(), template.IsDefault, "LogDate", metodo, dateTime);
            return reportByte;
        }


        [WebMethod(MessageName = "CreaReportOld")]        
        public byte[] CreaReportOld(long chiave, Template template, List<Parametro> parametri)
        {
            //((Opzione2)JsonConvert.DeserializeObject((from o in template.Options where o.Key == "Opzione2" select o.Value).LastOrDefault<string>(), typeof(Opzione2))).ChiaveProposta
            

            // Modello
            var mt = new WebTemplateModelerService();
            template = mt.TestTemplate(template, "CreaReportOld");
            var modello = mt.GetModello(template.IdModello);
             
            //******             
            string Opzione2 = (from o in template.Options where o.Key == "Opzione2" select o.Value).LastOrDefault<string>();
            var cliente = Consulenza.DataServices.DatiSeiUnico.GetMokCliente(chiave);

            Consulenza.DataServices.DatiSeiUnico datiSeiUnico = new Consulenza.DataServices.DatiSeiUnico(
                cliente.codiceAgente,
                cliente.codiceFiscale,
                cliente.codiceMandato,
                cliente.codiceRete,
                Opzione2 != null ? ((Opzione2)JsonConvert.DeserializeObject(Opzione2, typeof(Opzione2))).ChiaveProposta : 0,
                !modello.Nome.ToLower().Equals("nucleo") ? 0 : chiave,
                (from s in template.Schede select s.Id).ToList<int>()
            );
            datiSeiUnico.Execute();
            //********
             

            // Struttura del report
            var strutturaReport = new ReportStruct
            {
                Opzioni = template.Options.Distinct().ToDictionary(x => x.Key, x => x.Value),
                Schede = (from schede in template.Schede
                          join modelli in modello.Schede
                              on schede.Id equals modelli.Id
                          select new ReportCommon.Scheda
                          {
                              Id = Convert.ToInt32(modelli.Sezioni),
                              Opzioni = schede.Options.Distinct().ToDictionary(x => x.Key, x => x.Value)
                          }).ToList()
            };


            //Propago le Opzioni a livello Report (per ora solo Opzione1 e Opzione2) a tutte le schede           
            foreach (var scheda in strutturaReport.Schede)
            {
                if (strutturaReport.Opzioni.ContainsKey("Opzione1"))
                    scheda.Opzioni.Add("Opzione1", strutturaReport.Opzioni["Opzione1"]); // Report anonimo o nominativo

                if (strutturaReport.Opzioni.ContainsKey("Opzione2"))
                    scheda.Opzioni.Add("Opzione2", strutturaReport.Opzioni["Opzione2"]); // ChiaveProposta
            }

            //Switch per report 
            switch (modello.Nome.ToLower())
            {
                case "diagnosi":
                    return new GeneratorService(chiave).CreaReport_Diagnosi(strutturaReport);
                case "monitoraggio":
                    return new GeneratorService(chiave).CreaReport_Monitoraggio(strutturaReport);
                case "proposta":
                    return new GeneratorService(datiSeiUnico).CreaReport_Proposta(strutturaReport);
                case "nucleo":
                    return new GeneratorService(datiSeiUnico).CreaReport_Nucleo(strutturaReport);
                default:
                    throw new Exception("Report non esistente");
            }
        }


    

        /// <summary>
        /// metodo da cancellare usato per gestire sviluppo separato da webtemplatemodeler db: le schede S74 S75 non sono incluse...tanto funzionano
        /// </summary>
        /// <param name="nomemodello"></param>
        /// <returns></returns>
        private List<WebTemplateModeler.Entity.Scheda> getModelloMoKKato(string nomemodello)
        {
            var lista = new List<WebTemplateModeler.Entity.Scheda>();
            int idscheda = 785;
            int idsezione = 44;

            for (int i = 1; i <= 16; i++)
            {
                var scheda = new WebTemplateModeler.Entity.Scheda
                {
                    Id = idscheda,
                    Options = new List<Option>(),
                    Sezioni = idsezione.ToString()
                };
                lista.Add(scheda);
                idscheda++;
                idsezione++;
            }
            switch (nomemodello.ToLower())
            {
                case "diagnosi":
                    lista.RemoveAll(o => o.Id == 787);
                    lista.RemoveAll(o => o.Id == 796);
                    break;
                case "monitoraggio":
                    lista.RemoveAll(o => o.Id == 787);
                    lista.RemoveAll(o => o.Id == 796);
                    break;
                case "proposta":
                    lista.RemoveAll(o => o.Id == 787);
                    lista.RemoveAll(o => o.Id == 788);
                    lista.RemoveAll(o => o.Id == 789);
                    lista.RemoveAll(o => o.Id == 790);
                    lista.RemoveAll(o => o.Id == 794);
                    lista.RemoveAll(o => o.Id == 795);
                    lista.RemoveAll(o => o.Id == 793);
                    lista.RemoveAll(o => o.Id == 796);
                    break;
                case "nucleo":
                    lista.RemoveAll(o => o.Id == 786);
                    lista.RemoveAll(o => o.Id == 793);
                    break;

            }
            return lista;
        }

        [WebMethod(MessageName = "GetModelli")]
        public List<Modello> GetModelli()
        {
            return new WebTemplateModelerService().GetModelli();
        }

        [WebMethod(MessageName = "GetModello")]
        public Modello GetModello(int idModello, string codicePb)
        {
            return new WebTemplateModelerService().GetModello(idModello, codicePb);
        }

        [WebMethod(MessageName = "GetVincoliNoChiave")]
        public List<Vincolo> GetVincoliNoChiave(string codiceAgente, string codiceFiscale, string codiceMandato, string codiceRete, long proposta, string modello)
        {
            return new WebTemplateModelerService().GetVincoliNoChiave(codiceAgente, codiceFiscale, codiceMandato, codiceRete, proposta, modello);
        }

        [WebMethod(MessageName = "GetVincoli")]
        public List<Vincolo> GetVincoli(long chiave,long proposta, string modello)
        {
            return new WebTemplateModelerService().GetVincoli(chiave,proposta, modello);
        }

        [WebMethod(MessageName = "GetTemplates")]
        public List<Template> GetTemplates(int idModello, string codicePb)
        {
            return new WebTemplateModelerService().GetTemplates(idModello, codicePb);
        }

        [WebMethod(MessageName = "GetTemplate")]
        public Template GetTemplate(int idTemplate, string isDefault)
        {
            return new WebTemplateModelerService().GetTemplate(idTemplate, isDefault);
        }

        [WebMethod(MessageName = "GetSchedeTemplate")]
        public List<SchedaTemplate> GetSchedeTemplate(int idTemplate, string isDefault)
        {
            return new WebTemplateModelerService().GetSchedeTemplate(idTemplate, isDefault);
        }

        [WebMethod(MessageName = "SetTemplate")]
        public int SetTemplate(int idModello, string codicePb, string nomeTemplate, List<Option> opzTemplate, List<SchedaTemplate> schede)
        {
            var mt = new WebTemplateModelerService();
            int idTemplate = mt.SetTemplate(idModello, codicePb, nomeTemplate, opzTemplate, schede);
            return idTemplate;
        }

        [WebMethod(MessageName = "DelTemplate")]
        public int DelTemplate(int idTemplate)
        {

            return new WebTemplateModelerService().DelTemplate(idTemplate);
        }

        [WebMethod(MessageName = "SetDocumentPdf")]
        public long SetDocumentPdf(DocumentoPdf documentoPdf, string idProvenienza)
        {
            return new ReportArchiveService().SetDocumentPdf(documentoPdf, idProvenienza);
        }

        [WebMethod(MessageName = "SetStato")]
        public int SetStato(long idPdf, string idstato, string idProvenienza)
        {
            return new ReportArchiveService().SetStato(idPdf, idstato, idProvenienza);
        }

        [WebMethod(MessageName = "GetlogPdf")]
        public List<LogPdf> GetlogPdf(long idPdf)
        {
            return new ReportArchiveService().GetlogPdf(idPdf);
        }

        [WebMethod(MessageName = "GetPdfs")]
        public List<DocumentoPdf> GetPdfs(RicercaPdf ricercaPdf)
        {
            return new ReportArchiveService().GetPdfs(ricercaPdf);
        }

        [WebMethod(MessageName = "GetPdf")]
        public DocumentoPdf GetPdf(long idPdf)
        {
            return new ReportArchiveService().GetPdf(idPdf);
        }

    }
}
