using Back.Common;
using Back.Data.Models;
using Back.Services;
using Back.Validations;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Shared.DTOs;
using Shared.DTOs.Serch;

namespace Back.Controllers
{
    [Route("api/[controller]")]
    [Authorize]
    [ApiController]
    public class InvoiceController : ControllerBase
    {
        private readonly servInvoice _servInvoice;
        private readonly servUser _servUser;
        private readonly AddOrUpdateInvoiceValidation _validationInvoice;
        private readonly servTaxPayer _servTaxPayer;
        public InvoiceController(servInvoice servInvoice, servUser servUser, AddOrUpdateInvoiceValidation validationInvoice, servTaxPayer servTaxPayer)
        {
            _servInvoice = servInvoice;
            _servUser = servUser;
            _validationInvoice = validationInvoice;
            _servTaxPayer = servTaxPayer;

        }
        [HttpPost("GetAll")]
        public async Task<ActionResult<PagingDto<InvoiceGridDTO>?>> GetAll([FromBody] ItemSerchGetInvoices itemSerch)
        {
            var claim = HttpContext.User.Claims.First(c => c.Type == "UserID");
            var UserID = claim.Value;
            var user = await _servUser.GetUserByUserID(Convert.ToInt32(UserID));

            return Ok(await _servInvoice.GetInvoices(user.RolUsers.First().CompanyID, itemSerch));

        }
        [HttpGet("Get/{ID}/{loaddelete}")]
        public async Task<ActionResult<InvoiceDTO?>> GetAll(int ID,bool loaddelete)
        {
            var claim = HttpContext.User.Claims.First(c => c.Type == "UserID");
            var UserID = claim.Value;
            var user = await _servUser.GetUserByUserID(Convert.ToInt32(UserID));
            var result = await _servInvoice.GetInvoice(user.RolUsers.First().CompanyID, ID,!loaddelete);

            return result==null ? BadRequest() : Ok(result);

        }
        [HttpPost("Add")]
        public async Task<ActionResult<int>> Add([FromBody] NUInvoiceDTO item)
        {
            if (string.IsNullOrEmpty(item.InvoiceDate))
                item.InvoiceDate = DateTime.Now.ConvertMiladiToShamsi();

            if (string.IsNullOrEmpty(item.InvoicIssueDate))
                item.InvoicIssueDate = DateTime.Now.ConvertMiladiToShamsi();


            //if (!ModelState.IsValid)
            //    return BadRequest(item);

            //-----GetUserAndCompany
            var claim =  HttpContext.User.Claims.First(c => c.Type == "UserID");
            var UserID = claim.Value;
            var user = await _servUser.GetUserByUserID(Convert.ToInt32(UserID));

            //-----Validaton
            var resultValidationmodel = await _validationInvoice.ValidateAsync(Tuple.Create(user.RolUsers.First().CompanyID, item, eActionValidation.add));
            if (!resultValidationmodel.IsValid)
                return BadRequest(resultValidationmodel.Errors.Select(s => s.ErrorMessage).ToList());


            //if (item.BillReference.HasValue)
            //{
            //    Invoice ReferenceInvoice = await _servInvoice.GetInvoiceByInvoiceID(item.BillReference.Value);
            //    if (ReferenceInvoice == null) return NotFound("صورتحساب مرجع یافت نشد");

            //    if (await _servCompany.ExsistCompanyByComoanyIDandUserID(UserID, ReferenceInvoice.CompanyID.Value)) return Forbid("صورتحساب مرجع برای شما در دسترس نمی باشد");
            //}


            return Ok(await _servInvoice.AddInvoice(new Invoice()
            {

                Title = item.Title,
                Des = item.Des,
                invoiceType = InvoiceType.Bidding,
                CustomerID = item.CustomerID,
                CompanyID = user.RolUsers.First().CompanyID,
                InvoicIssueDate = item.InvoicIssueDate.Replace("/", ""),
                InvoiceDate = item.InvoicIssueDate.Replace("/", ""),
                LastChangeUserID = Convert.ToInt32(UserID),
                BillReference = null,
                IsDeleted = false,
                PatternID = item.PatternID,
                setm=1
            }));



        }
        [HttpPut("Update")]
        public async Task<ActionResult<bool>> Update([FromBody] NUInvoiceDTO item)
        {
            //if (!ModelState.IsValid)
            //    return BadRequest(item);

            //-----GetUserAndCompany
            var claim = HttpContext.User.Claims.First(c => c.Type == "UserID");
            var UserID = claim.Value;
            var user = await _servUser.GetUserByUserID(Convert.ToInt32(UserID));

            //-----Validaton
            var resultValidationmodel = await _validationInvoice.ValidateAsync(Tuple.Create(user.RolUsers.First().CompanyID, item, eActionValidation.update));
            if (!resultValidationmodel.IsValid)
                return BadRequest(resultValidationmodel.Errors.Select(s => s.ErrorMessage).ToList());

            //-----Get invoice
            Invoice invoice = await _servInvoice.GetInvoiceByInvoiceID(user.RolUsers.First().CompanyID, item.ID.Value);
            if (invoice == null)
                return BadRequest(new List<string> { "invoice notFound..." });

            if (invoice.PatternID != item.PatternID || invoice.CustomerID != item.CustomerID
                    || invoice.InvoicIssueDate != item.InvoicIssueDate || invoice.InvoiceDate != item.InvoiceDate)
            {
                //----Check TaxPayer
                if (await _servTaxPayer.ExistSuccessfulorSendorpendingInvoice(invoice))
                    return BadRequest(new List<string> { "این صورتحساب به سازمان ارسال شده"+'\n'+
                        "برای تغییر ،صورتحساب را ابطال/اصلاح یا برگشت بزنید"});
                else if (invoice.invoiceType == InvoiceType.BackFrmSale)
                {
                    return BadRequest(new List<string>
                    { "صورتحساب در وضعیت برگشت از فروش نمی تواند ویرایش شود" });
                }
                else if (invoice.invoiceType != InvoiceType.Bidding
                        && invoice.invoiceType != InvoiceType.Sale && invoice.invoiceType != InvoiceType.Repair)
                {
                    return BadRequest(new List<string> { $"صورتحساب در حالت {invoice.invoiceType.GetEnumDisplayName()} نمی تواند ویرایش شود"+'\n'+
                                 $"فقط در حالت پیش نویس ، فاکتور و اصلاح (که به سازمان ارسال نشده باشد) میتوان سند را ویرایش کرد" });
                }
            }



            //-----change invoice
            if (!string.IsNullOrEmpty(item.Title))
                invoice.Title = item.Title;

            invoice.PatternID = item.PatternID;

            if (item.CustomerID > 0)
                invoice.CustomerID = item.CustomerID;

            if (!string.IsNullOrEmpty(item.InvoicIssueDate))
                invoice.InvoicIssueDate = item.InvoicIssueDate;

            if (!string.IsNullOrEmpty(item.InvoiceDate))
                invoice.InvoiceDate = item.InvoiceDate;

            invoice.Des = item.Des;
            invoice.LastChangeUserID = Convert.ToInt32(UserID);

            return Ok(await _servInvoice.UpdateInvoice(invoice));
        }
        [HttpDelete("Delete/{ID}")]
        public async Task<ActionResult<bool>> Delete(int ID)
        {
            //-----GetUserAndCompany
            var claim = HttpContext.User.Claims.First(c => c.Type == "UserID");
            var UserID = claim.Value;
            var user = await _servUser.GetUserByUserID(Convert.ToInt32(UserID));

            //-----Get invoice
            Invoice invoice = await _servInvoice.GetInvoiceByInvoiceID(user.RolUsers.First().CompanyID, ID);
            if (invoice == null)
                return NotFound();


            //----Check TaxPayer
            if (await _servTaxPayer.ExistSuccessfulorSendorpendingInvoice(invoice))
                return BadRequest(new List<string> { "این صورتحساب به سازمان ارسال شده"});
            //else if (invoice.invoiceType != InvoiceType.Bidding
            //        && invoice.invoiceType != InvoiceType.Sale)
            //{
            //    return BadRequest(new List<string> { $"صورتحساب در حالت {invoice.invoiceType.GetEnumDisplayName()} نمی تواند ویرایش شود" });
            //}

            invoice.LastChangeUserID = Convert.ToInt32(UserID);
            //----Update and sendResult
            return Ok(await _servInvoice.DeleteInvoice(invoice));
        }
        [HttpPost("ChangeInvoiceType/{InvoiceID}")]// ok
        public async Task<ActionResult<InvoiceDTO>> ChangeInvoiceType(int InvoiceID, int invoiceType)
        {
            //-----GetUserAndCompany
            var claim = HttpContext.User.Claims.First(c => c.Type == "UserID");
            var UserID = claim.Value;
            var user = await _servUser.GetUserByUserID(Convert.ToInt32(UserID));

            Invoice? Invoice = await _servInvoice.GetInvoiceByInvoiceID(user.RolUsers.First().CompanyID, InvoiceID);
            if (Invoice == null) return NotFound();

            if (Invoice.invoiceType == InvoiceType.Cancellation) return BadRequest(new List<string> { "این صورتحساب ابطال شده" });
            var sent = await _servTaxPayer.ExistSuccessfulorSendorpendingInvoice(Invoice);
            Invoice.LastChangeUserID = Convert.ToInt32(UserID);
            if (Invoice.invoiceType == InvoiceType.Bidding)
            {
                switch (invoiceType)
                {
                    case 1:
                        return Ok(await _servInvoice.ChangeInvoiceType(Invoice, InvoiceType.Sale));

                    case 3:
                        return Ok(await _servInvoice.ChangeInvoiceType(Invoice, InvoiceType.Cancellation));
                    //case 0:
                    //    return Ok(await _servInvoice.ChangeInvoiceType(Invoice, InvoiceType.CANCEL));

                    default:
                        return BadRequest(new List<string> { $"تغییر وضعیت از {Invoice.invoiceType.GetEnumDisplayName()} به {((InvoiceType)invoiceType).GetEnumDisplayName()} امکان پذیر نیست" });
                }
            }
            if (Invoice.invoiceType == InvoiceType.Sale)
            {
                //if (sent)
                //{
                    switch (invoiceType)
                    {
                        //case 0:
                        //    return Ok(await _servInvoice.ChangeInvoiceType(Invoice, InvoiceType.CANCEL));

                        case 3:
                            return Ok(await _servInvoice.ChangeInvoiceType(Invoice, InvoiceType.Cancellation));

                        case 2:
                            await _servInvoice.ChangeInvoiceType(Invoice, InvoiceType.Repair, false);
                            var result = await _servInvoice.AddInvoice(new Invoice()
                            {

                                Title = Invoice.Title,
                                Des = Invoice.Des,
                                invoiceType = InvoiceType.Repair,
                                CustomerID = Invoice.CustomerID,
                                CompanyID = Invoice.CompanyID,
                                InvoicIssueDate = Invoice.InvoicIssueDate.Replace("/", ""),
                                InvoiceDate = Invoice.InvoicIssueDate.Replace("/", ""),
                                LastChangeUserID = Convert.ToInt32(UserID),
                                BillReference = Invoice.ID,
                                IsDeleted = false,
                                PatternID = Invoice.PatternID,
                                setm=Invoice.setm,
                                invoiceDetails=Invoice.invoiceDetails.Select(s=>new InvoiceItem
                                {
                                    CODID=s.CODID,
                                    am=s.am,
                                    fee=s.fee,
                                    dis=s.dis,
                                    
                                }).ToList()
                            }, false);
                            if (result > 0)
                            return Ok(await _servInvoice.GetInvoice(user.RolUsers.First().CompanyID,result));
                            break;
                        case 4:
                            await _servInvoice.ChangeInvoiceType(Invoice, InvoiceType.BackFrmSale, false);
                            var result1 = await _servInvoice.AddInvoice(new Invoice()
                            {

                                Title = Invoice.Title,
                                Des = Invoice.Des,
                                invoiceType = InvoiceType.BackFrmSale,
                                CustomerID = Invoice.CustomerID,
                                CompanyID = Invoice.CompanyID,
                                InvoicIssueDate = Invoice.InvoicIssueDate.Replace("/", ""),
                                InvoiceDate = Invoice.InvoicIssueDate.Replace("/", ""),
                                LastChangeUserID = Convert.ToInt32(UserID),
                                BillReference = Invoice.ID,
                                IsDeleted = false,
                                PatternID = Invoice.PatternID,
                                setm = Invoice.setm,
                                invoiceDetails = Invoice.invoiceDetails.Select(s => new InvoiceItem
                                {
                                    CODID = s.CODID,
                                    am = s.am,
                                    fee = s.fee,
                                    dis = s.dis,

                                }).ToList()
                            }, false);
                            if (result1 > 0)
                                return Ok(await _servInvoice.GetInvoice(user.RolUsers.First().CompanyID, result1));
                            break;

                        default:
                            return BadRequest(new List<string> { $"تغییر وضعیت از {Invoice.invoiceType.GetEnumDisplayName()} به {((InvoiceType)invoiceType).GetEnumDisplayName()} امکان پذیر نیست این صورتحساب به سامانه مودیان ارسال شده" });
                    }
                //}
                //else
                //{
                //    switch (invoiceType)
                //    {
                //        case 0:
                //            return Ok(await _servInvoice.ChangeInvoiceType(Invoice, InvoiceType.CANCEL));

                //        default:
                //            return BadRequest(new List<string> { $"تغییر وضعیت از {Invoice.invoiceType.GetEnumDisplayName()} به {((InvoiceType)invoiceType).GetEnumDisplayName()} امکان پذیر نیست" });
                //    }

                //}
            }
            //if (Invoice.invoiceType == InvoiceType.Cancellation)
            //{
            //    if (!sent)
            //    {
            //        switch (invoiceType)
            //        {
            //            //case InvoiceType.Sale:
            //            //    return Ok(await _servInvoice.ChangeInvoiceType(Invoice, invoiceType));

            //            case 0:
            //                return Ok(await _servInvoice.ChangeInvoiceType(Invoice, InvoiceType.CANCEL));

            //            default:
            //                return BadRequest(new List<string> { $"تغییر وضعیت از {Invoice.invoiceType.GetEnumDisplayName()} به {((InvoiceType)invoiceType).GetEnumDisplayName()} امکان پذیر نیست" });
            //        }
            //    }
            //    else return BadRequest(new List<string> { $"تغییر وضعیت از {Invoice.invoiceType.GetEnumDisplayName()} به {((InvoiceType)invoiceType).GetEnumDisplayName()} امکان پذیر نیست این صورتحساب به سامانه مودیان ارسال شده" });
            //}
            if (Invoice.invoiceType == InvoiceType.Repair)
            {
                //if (!sent)
                //{
                //    switch (invoiceType)
                //    {
                //        case 0:
                //            return Ok(await _servInvoice.ChangeInvoiceType(Invoice, InvoiceType.CANCEL));

                //        default:
                //            return BadRequest(new List<string> { $"تغییر وضعیت از {Invoice.invoiceType.GetEnumDisplayName()} به {((InvoiceType)invoiceType).GetEnumDisplayName()} امکان پذیر نیست" });
                //    }
                //}
                //else
                //{
                    switch (invoiceType)
                    {
                        case 3:
                            return Ok(await _servInvoice.ChangeInvoiceType(Invoice, InvoiceType.Cancellation));

                        case 4:
                            await _servInvoice.ChangeInvoiceType(Invoice, InvoiceType.BackFrmSale, false);
                            var result2 = await _servInvoice.AddInvoice(new Invoice()
                            {

                                Title = Invoice.Title,
                                Des = Invoice.Des,
                                invoiceType = InvoiceType.BackFrmSale,
                                CustomerID = Invoice.CustomerID,
                                CompanyID = Invoice.CompanyID,
                                InvoicIssueDate = Invoice.InvoicIssueDate.Replace("/", ""),
                                InvoiceDate = Invoice.InvoicIssueDate.Replace("/", ""),
                                LastChangeUserID = Convert.ToInt32(UserID),
                                BillReference = Invoice.ID,
                                IsDeleted = false,
                                PatternID = Invoice.PatternID,
                                setm = Invoice.setm,
                                invoiceDetails =Invoice.invoiceDetails.Select(s => new InvoiceItem
                                {
                                    CODID = s.CODID,
                                    am = s.am,
                                    fee = s.fee,
                                    dis = s.dis,

                                }).ToList()
                            }, false);
                            if (result2 > 0)
                                return Ok(await _servInvoice.GetInvoice(user.RolUsers.First().CompanyID, result2));
                            break;

                        default:
                            return BadRequest(new List<string> { $"تغییر وضعیت از {Invoice.invoiceType.GetEnumDisplayName()} به {((InvoiceType)invoiceType).GetEnumDisplayName()} امکان پذیر نیست این صورتحساب به سامانه مودیان ارسال شده" });

                    }
                //}
            }
            if (Invoice.invoiceType == InvoiceType.BackFrmSale)
            {
               // if (!sent)
               // {
                    switch (invoiceType)
                    {
                        //case 0:
                        //    return Ok(await _servInvoice.ChangeInvoiceType(Invoice, InvoiceType.CANCEL));

                        case 3:
                            return Ok(await _servInvoice.ChangeInvoiceType(Invoice, InvoiceType.Cancellation));
                        default:
                            return BadRequest(new List<string> { $"تغییر وضعیت از {Invoice.invoiceType.GetEnumDisplayName()} به {((InvoiceType)invoiceType).GetEnumDisplayName()} امکان پذیر نیست" });
                    }
               // }
                //else
                //{
                //    switch (invoiceType)
                //    {
                //        case 3:
                //            return Ok(await _servInvoice.ChangeInvoiceType(Invoice, InvoiceType.Cancellation));

                //        //case InvoiceType.Repair:
                //        //    await _servInvoice.ChangeInvoiceType(Invoice, invoiceType, false);
                //        //    return Ok(await _servInvoice.AddInvoice(new Invoice()
                //        //    {

                //        //        Title = Invoice.Title,
                //        //        Des = Invoice.Des,
                //        //        invoiceType = invoiceType,
                //        //        CustomerID = Invoice.CustomerID,
                //        //        CompanyID = Invoice.CompanyID,
                //        //        InvoicIssueDate = Invoice.InvoicIssueDate.Replace("/", ""),
                //        //        InvoiceDate = Invoice.InvoicIssueDate.Replace("/", ""),
                //        //        LastChangeUserID = Convert.ToInt32(UserID),
                //        //        BillReference = Invoice.ID,
                //        //        IsDeleted = false,
                //        //        PatternID = Invoice.PatternID
                //        //    }, false));

                //        default:
                //            return BadRequest(new List<string> { $"تغییر وضعیت از {Invoice.invoiceType.GetEnumDisplayName()} به {((InvoiceType)invoiceType).GetEnumDisplayName()} امکان پذیر نیست این صورتحساب به سامانه مودیان ارسال شده" });

                //    }
                //}
            }


            return NoContent();

        }
        [HttpGet("GetPatterns")]
        public async Task<ActionResult<List<IdName<int>>>> GetPatterns()
        {
            return Ok(await _servTaxPayer.GetPatterns());
        }
        [HttpGet("GetReport/{InvoiceID}")]
        public IActionResult GetReport(int InvoiceID)
        {
            var reportPath = $"Reports\\invoice.mrt";
            var bytes = System.IO.File.ReadAllBytes(reportPath);
            return new FileContentResult(bytes, "application/xml");
        }
    }
}
