using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using QuizplusApi.Models;
using QuizplusApi.Models.Others;
using QuizplusApi.Services;
using QuizplusApi.ViewModels.Email;
using QuizplusApi.ViewModels.Helper;
using QuizplusApi.ViewModels.Payment;
using QuizplusApi.ViewModels.User;

namespace QuizplusApi.Controllers
{
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class SettingsController:ControllerBase
    {
        private readonly AppDbContext _context;
        private readonly ISqlRepository<Faq> _faqRepo;
        private readonly ISqlRepository<Contacts> _contactRepo;
        private readonly ISqlRepository<BillingPlan> _planRepo;
        private readonly ISqlRepository<BillingPayment> _billingRepo;
        private readonly IMailService _mailService;

        public SettingsController(AppDbContext context,
                                ISqlRepository<Faq> faqRepo,
                                ISqlRepository<Contacts> contactRepo,
                                ISqlRepository<BillingPlan> planRepo,
                                ISqlRepository<BillingPayment> billingRepo,
                                IMailService mailService)
        {
            _context=context;
            _faqRepo=faqRepo;
            _contactRepo=contactRepo;
            _planRepo=planRepo;
            _billingRepo=billingRepo;
            _mailService=mailService;
        }

        ///<summary>
        ///Sent Password Email
        ///</summary>
        [HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> SendPasswordMail(ForgetPassword request)
        {
            try
            {
                await _mailService.SendPasswordEmailAsync(request);
                return Ok(new Confirmation { Status = "success", ResponseMsg = "Please check your Email"});
            }
            catch (Exception ex)
            {
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });
            }              
        }

        ///<summary>
        ///Sent Welcome Email
        ///</summary>
        [HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> SendWelcomeMail(WelcomeRequest request)
        {
            try
            {
                await _mailService.SendWelcomeEmailAsync(request);
                return Ok(new Confirmation { Status = "success", ResponseMsg = "Email sent Successful"});
            }
            catch (Exception ex)
            {
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });
            }
        }

        ///<summary>
        ///Sent Email to checked students
        ///</summary>
        [HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> SentEmailToCheckedStudents(ReExamRequest obj)
        {
            try
            {              
                await _mailService.SendReportEmailAsync(obj); 
                return Ok();           
            }
            catch (Exception ex)
            {              
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });
            }
        }

        ///<summary>
        ///Sent Invitation Email
        ///</summary>
        [HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> SendInvitationMail(List<Invitation> listOfAddress)
        {
            try
            {
                await _mailService.SendInvitationEmailAsync(listOfAddress);
                return Ok(new Confirmation { Status = "success", ResponseMsg = "Email sent Successful"});
            }
            catch (Exception ex)
            {
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });
            }
        }

        ///<summary>
        ///Get Site Settings by User id
        ///</summary>
        [HttpGet("{userId}")]
        [AllowAnonymous]
        public ActionResult GetSiteSettingsByUserId(int userId)
        {
            try
            {              
                var siteSettings=_context.SiteSettings.FirstOrDefault(q=>q.AddedBy==userId);
                return Ok(siteSettings);           
            }
            catch (Exception ex)
            {              
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });
            }
        }

        ///<summary>
        ///Update Settings for Admin
        ///</summary>
        [Authorize(Roles="Admin")]
        [HttpPut]       
        public ActionResult UpdateSettingsAdmin(PaymentSettings model)
        {
            try
            {
                var objSettings=_context.SiteSettings.FirstOrDefault(opt=>opt.AddedBy==model.AddedBy);
                objSettings.StripeSecretKey=model.StripeSecretKey;
                objSettings.ClientUrl=model.ClientUrl;
                objSettings.LastUpdatedBy=model.AddedBy;
                objSettings.LastUpdatedDate=DateTime.Now;
                _context.SaveChanges();
                return Ok(objSettings);                                           
            }
            catch (Exception ex)
            {
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });             
            }
        }

        ///<summary>
        ///Get Quiz Payments by User id
        ///</summary>
        [HttpGet("{adminId}")]
        [AllowAnonymous]
        public ActionResult GetQuizPaymentsByUserId(int adminId)
        {
            try
            {
                var data=from p in _context.QuizPayments join q in _context.QuizTopics on p.QuizTopicId
                equals q.QuizTopicId join u in _context.Users on p.AddedBy equals u.UserId
                where p.AdminId.Equals(adminId) orderby p.DateAdded descending
                select new {q.QuizTitle,q.QuizPrice,p.Amount,p.Email,p.Currency,p.SessionId,u.FullName,p.DateAdded};
                return Ok(data);           
            }
            catch (Exception ex)
            {              
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });
            }
        }
        ///<summary>
        ///Get Site Settings
        ///</summary>
        [HttpGet]
        [AllowAnonymous]
        public ActionResult GetSiteSettings()
        {
            try
            {              
                var siteSettings=_context.SiteSettings.OrderBy(q=>q.SiteSettingsId).FirstOrDefault();
                return Ok(siteSettings);           
            }
            catch (Exception ex)
            {              
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });
            }
        }

        ///<summary>
        ///Update Settings
        ///</summary>
        [Authorize(Roles="SuperAdmin")]
        [HttpPut]       
        public ActionResult UpdateSettings(SiteSettings model)
        {
            try
            {
                var objSettings=_context.SiteSettings.SingleOrDefault(opt=>opt.SiteSettingsId==model.SiteSettingsId);
                objSettings.SiteTitle=model.SiteTitle;
                objSettings.WelComeMessage=model.WelComeMessage;
                objSettings.CopyRightText=model.CopyRightText;
                objSettings.Version=model.Version;
                objSettings.EndExam=model.EndExam;
                objSettings.LogoOnExamPage=model.LogoOnExamPage;
                objSettings.PaidRegistration=model.PaidRegistration;
                objSettings.RegistrationPrice=model.RegistrationPrice==null?0:model.RegistrationPrice;
                objSettings.Currency=model.Currency;
                objSettings.CurrencySymbol=model.CurrencySymbol;
                objSettings.StripePubKey=model.StripePubKey;
                objSettings.StripeSecretKey=model.StripeSecretKey;
                objSettings.DefaultEmail=model.DefaultEmail;
                objSettings.Password=model.Password;
                objSettings.Host=model.Host;
                objSettings.Port=model.Port;
                objSettings.LogoPath=model.LogoPath;
                objSettings.FaviconPath=model.FaviconPath;
                objSettings.AppBarColor=model.AppBarColor;
                objSettings.FooterColor=model.FooterColor;
                objSettings.BodyColor=model.BodyColor;
                objSettings.AllowWelcomeEmail=model.AllowWelcomeEmail;
                objSettings.AllowFaq=model.AllowFaq;
                objSettings.LastUpdatedBy=model.LastUpdatedBy;
                objSettings.LastUpdatedDate=DateTime.Now;
                _context.SaveChanges();
                return Ok(objSettings);                                           
            }
            catch (Exception ex)
            {
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });             
            }
        }

        ///<summary>
        ///Update Client Url
        ///</summary>
        [AllowAnonymous]
        [HttpPut]       
        public ActionResult UpdateClientUrl(UserInfo model)
        {
            try
            {
                var objSettings=_context.SiteSettings.SingleOrDefault();
                objSettings.ClientUrl=model.DisplayName;
                _context.SaveChanges();
                return Ok(new Confirmation { Status = "success", ResponseMsg = "Successfully saved" });
            }
            catch (Exception ex)
            {
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });             
            }
        }
        ///<summary>
        ///Site Logo upload
        ///</summary>
        [Authorize(Roles="SuperAdmin")]   
        [HttpPost, DisableRequestSizeLimit]
        public IActionResult UploadLogo()
        {
            try
            {
                var file = Request.Form.Files[0];
                var folderName = Path.Combine("Resources", "Logo");
                var pathToSave = Path.Combine(Directory.GetCurrentDirectory(), folderName);

                if (file.Length > 0 && file.ContentType.StartsWith("image/"))
                {
                    var fileName = Guid.NewGuid().ToString()+"_"+ ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');                  
                    var fullPath = Path.Combine(pathToSave, fileName);
                    var dbPath = Path.Combine(folderName, fileName);

                    using (var stream = new FileStream(fullPath, FileMode.Create))
                    {
                        file.CopyTo(stream);
                    }

                    return Ok(new { dbPath });                   
                }
                else
                {
                    return Accepted(new Confirmation { Status = "error", ResponseMsg = "Not an image" }); 
                }
            }
            catch (Exception ex)
            {
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });               
            }
        }

        ///<summary>
        ///Site Favicon upload
        ///</summary>
        [Authorize(Roles="SuperAdmin")]   
        [HttpPost, DisableRequestSizeLimit]
        public IActionResult UploadFavicon()
        {
            try
            {
                var file = Request.Form.Files[0];
                var folderName = Path.Combine("Resources", "Favicon");
                var pathToSave = Path.Combine(Directory.GetCurrentDirectory(), folderName);

                if (file.Length > 0 && file.ContentType.StartsWith("image/"))
                {
                    var fileName = Guid.NewGuid().ToString()+"_"+ ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');                  
                    var fullPath = Path.Combine(pathToSave, fileName);
                    var dbPath = Path.Combine(folderName, fileName);

                    using (var stream = new FileStream(fullPath, FileMode.Create))
                    {
                        file.CopyTo(stream);
                    }

                    return Ok(new { dbPath });                   
                }
                else
                {
                    return Accepted(new Confirmation { Status = "error", ResponseMsg = "Not an image" }); 
                }
            }
            catch (Exception ex)
            {
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });               
            }
        }

        ///<summary>
        ///Get FAQ List
        ///</summary>
        [HttpGet]
        [Authorize(Roles="Admin,SuperAdmin,Student")]
        public ActionResult GetFaqList()
        {
            try
            {              
                var faqList=_faqRepo.SelectAll();
                return Ok(faqList);           
            }
            catch (Exception ex)
            {              
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });
            }
        }

        ///<summary>
        ///Delete FAQ by Id
        ///</summary>
        [HttpDelete("{id}")]
        [Authorize(Roles="SuperAdmin")]
        public ActionResult DeleteFaq(int id)
        {
            try
            {      
                _faqRepo.Delete(id);
                return Ok(new Confirmation { Status = "success", ResponseMsg = "Successfully deleted" });                                             
            }
            catch (Exception ex)
            {              
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });
            }
        }

        ///<summary>
        ///Create Faq
        ///</summary>
        [Authorize(Roles="SuperAdmin")]
        [HttpPost]       
        public ActionResult CreateFaq(Faq model)
        {
            try
            {                  
                var objCheck=_context.Faqs.SingleOrDefault(opt=>opt.Title.ToLower()==model.Title.ToLower());
                if(objCheck==null)
                {
                    model.DateAdded=DateTime.Now;
                    model.IsActive=true;
                    _faqRepo.Insert(model);
                    return Ok(new Confirmation { Status = "success", ResponseMsg = "Successfully saved" });                  
                }
                else
                {
                    return Accepted(new Confirmation { Status = "duplicate", ResponseMsg = "Duplicate FAQ!" });
                }                    
            }
            catch (Exception ex)
            {
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });             
            }
        }

        ///<summary>
        ///Update Faq
        ///</summary>
        [Authorize(Roles="SuperAdmin")]
        [HttpPut]       
        public ActionResult UpdateFaq(Faq model)
        {
            try
            {
                var objFaq=_context.Faqs.SingleOrDefault(opt=>opt.FaqId==model.FaqId);
                var objCheck=_context.Faqs.SingleOrDefault(opt=>opt.Title.ToLower()==model.Title.ToLower());

                if(objCheck!=null && objCheck.Title.ToLower()!=objFaq.Title.ToLower())
                {
                    return Accepted(new Confirmation { Status = "duplicate", ResponseMsg = "Duplicate FAQ!" });
                }
                else
                {
                    objFaq.Title=model.Title;
                    objFaq.Description=model.Description;
                    objFaq.LastUpdatedBy=model.LastUpdatedBy;
                    objFaq.LastUpdatedDate=DateTime.Now;
                    _context.SaveChanges();
                    return Ok(new Confirmation { Status = "success", ResponseMsg = "Successfully updated" });
                }                                             
            }
            catch (Exception ex)
            {
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });             
            }
        }

        ///<summary>
        ///Create Contact-us
        ///</summary>
        [AllowAnonymous]
        [HttpPost]       
        public ActionResult CreateContacts(Contacts model)
        {
            try
            {                  
                model.DateAdded=DateTime.Now;
                _contactRepo.Insert(model);
                return Ok(new Confirmation { Status = "success", ResponseMsg = "Successfully submitted" });                    
            }
            catch (Exception ex)
            {
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });             
            }
        }

         ///<summary>
        ///Update Faq
        ///</summary>
        [Authorize(Roles="Admin,SuperAdmin")]
        [HttpPut]       
        public ActionResult RenewPlan(BillRegister model)
        {
            try
            {
                using var transaction = _context.Database.BeginTransaction();

                model.Price=_context.BillingPlans.FirstOrDefault(q=>q.BillingPlanId==model.BillingPlanId).Price;
                PaymentService objPaymentService=new PaymentService(_context);
                int paymentId=objPaymentService.InsertBillingPayment(model);

                var objUser=_context.Users.FirstOrDefault(q=>q.UserId==model.AddedBy);
                objUser.BillingPlanId=model.BillingPlanId;
                objUser.PaymentMode=model.PaymentMode;
                objUser.TransactionDetail=model.TransactionDetail;
                objUser.PaymentId=paymentId;
                _context.SaveChanges();

                transaction.Commit();  
                return Ok(new Confirmation { Status = "success", ResponseMsg = "Successfully renewed" });                                         
            }
            catch (Exception ex)
            {
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });             
            }
        }

        ///<summary>
        ///Get Contacts
        ///</summary>
        [HttpGet]
        [Authorize(Roles="SuperAdmin")]
        public ActionResult GetContacts()
        {
            try
            {              
                var list=_context.Contacts.OrderByDescending(q=>q.DateAdded);
                return Ok(list);           
            }
            catch (Exception ex)
            {              
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });
            }
        }

        ///<summary>
        ///Create Payment
        ///</summary>
        [AllowAnonymous]
        [HttpPost]       
        public ActionResult CreatePayment(BillRegister model)
        {
            try
            {       
                PaymentService objPaymentService=new PaymentService(_context);
                objPaymentService.InsertBillingPayment(model);
                return Ok();                   
            }
            catch (Exception ex)
            {
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });             
            }
        }

        ///<summary>
        ///Get Billing List
        ///</summary>
        [HttpGet]
        [Authorize(Roles="Admin,SuperAdmin")]
        public ActionResult GetBillingPaymentList()
        {
            try
            {              
                var list=_context.BillingPayments.OrderByDescending(q=>q.DateAdded);
                return Ok(list);           
            }
            catch (Exception ex)
            {              
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });
            }
        }


        ///<summary>
        ///Get Plan List
        ///</summary>
        [HttpGet]
        [AllowAnonymous]
        public ActionResult GetPlanList()
        {
            try
            {              
                var list=_context.BillingPlans.OrderBy(q=>q.Price);
                return Ok(list);           
            }
            catch (Exception ex)
            {              
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });
            }
        }

        ///<summary>
        ///Delete Plan by Id
        ///</summary>
        [HttpDelete("{id}")]
        [Authorize(Roles="SuperAdmin")]
        public ActionResult DeletePlan(int id)
        {
            try
            {   
                var chkMigration=_context.BillingPlans.FirstOrDefault(q=>q.BillingPlanId==id);
                if(chkMigration.IsMigrationData)
                {
                    return Accepted(new Confirmation { Status = "error", ResponseMsg = "Not allowed to delete this on demo version!" });
                }  
                else
                {
                    _planRepo.Delete(id);
                    return Ok(new Confirmation { Status = "success", ResponseMsg = "Successfully deleted" });
                }                                             
            }
            catch (Exception ex)
            {              
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });
            }
        }

        ///<summary>
        ///Create Plan
        ///</summary>
        [Authorize(Roles="SuperAdmin")]
        [HttpPost]       
        public ActionResult CreatePlan(BillingPlan model)
        {
            try
            {                  
                var objCheck=_context.BillingPlans.Where(opt=>opt.Title.ToLower()==model.Title.ToLower()
                || opt.Price==model.Price).FirstOrDefault();
                
                if(objCheck==null)
                {
                    model.DateAdded=DateTime.Now;
                    model.IsActive=true;
                    _planRepo.Insert(model);
                    return Ok(new Confirmation { Status = "success", ResponseMsg = "Successfully saved" });                  
                }
                else if(objCheck.Title.ToLower()==model.Title.ToLower())
                {
                    return Accepted(new Confirmation { Status = "duplicate", ResponseMsg = "Duplicate Title!" });
                }
                else if(objCheck.Price==model.Price)
                {
                    return Accepted(new Confirmation { Status = "duplicate", ResponseMsg = "Duplicate Price!" });
                }
                else
                {
                    return Accepted(new Confirmation { Status = "duplicate", ResponseMsg = "Something unexpected!" });
                }                    
            }
            catch (Exception ex)
            {
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });             
            }
        }

        ///<summary>
        ///Update Plan
        ///</summary>
        [Authorize(Roles="SuperAdmin")]
        [HttpPut]       
        public ActionResult UpdatePlan(BillingPlan model)
        {
            try
            {
                var objPlan=_context.BillingPlans.SingleOrDefault(opt=>opt.BillingPlanId==model.BillingPlanId);
                var objCheckTitle=_context.BillingPlans.SingleOrDefault(opt=>opt.Title.ToLower()==model.Title.ToLower());
                var objCheckPrice=_context.BillingPlans.SingleOrDefault(opt=>opt.Price==model.Price);

                if(objCheckTitle!=null && objCheckTitle.Title.ToLower()!=objPlan.Title.ToLower())
                {
                    return Accepted(new Confirmation { Status = "duplicate", ResponseMsg = "Duplicate Title!" });
                }
                else if(objCheckPrice!=null && objCheckPrice.Price!=objPlan.Price)
                {
                    return Accepted(new Confirmation { Status = "duplicate", ResponseMsg = "Duplicate Price!" });
                }
                else
                {
                    objPlan.Title=model.Title;
                    objPlan.Price=model.Price;
                    objPlan.Interval=model.Interval;
                    objPlan.AssessmentCount=model.AssessmentCount;
                    objPlan.QuestionPerAssessmentCount=model.QuestionPerAssessmentCount;
                    objPlan.ResponsePerAssessmentCount=model.ResponsePerAssessmentCount;
                    objPlan.AdditionalText=model.AdditionalText;
                    objPlan.LastUpdatedDate=DateTime.Now;
                    _context.SaveChanges();
                    return Ok(new Confirmation { Status = "success", ResponseMsg = "Successfully updated" });
                }                                             
            }
            catch (Exception ex)
            {
                return Accepted(new Confirmation { Status = "error", ResponseMsg = ex.Message });             
            }
        }
    }
}