using Back.Common;
using Back.Data.Contracts;
using Back.Data.Models;
using Back.Services;
using Back.Services.Warehouse;
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;
using Shared.Enums;
using System.Diagnostics;

namespace Back.Controllers
{
    [Route("api/[controller]")]
    [Authorize]
    [ApiController]
    public class InvoiceController : ControllerBase
    {
        private readonly IConfiguration _configuration;
        private readonly servInvoice _servInvoice;
        private readonly servUser _servUser;
        private readonly AddOrUpdateInvoiceValidation _validationInvoice;
        private readonly servTaxPayer _servTaxPayer;
        private readonly servReport _servReport;
        private readonly IAsyncRepository<rptQueue> _rptQueueRepository;
        private readonly RemittanceService _remittanceService;
        private readonly WarehouseService _warehouseService;
        private readonly ReceiptService _receiptService;

        public InvoiceController(IConfiguration configuration, servInvoice servInvoice, servUser servUser, AddOrUpdateInvoiceValidation validationInvoice, servTaxPayer servTaxPayer, servReport servReport, IAsyncRepository<rptQueue> rptQueueRepository, RemittanceService remittanceService, WarehouseService warehouseService, ReceiptService receiptService)
        {
            _configuration = configuration;
            _servInvoice = servInvoice;
            _servUser = servUser;
            _validationInvoice = validationInvoice;
            _servTaxPayer = servTaxPayer;
            _servReport = servReport;
            _rptQueueRepository = rptQueueRepository;
            _remittanceService = remittanceService;
            _warehouseService = warehouseService;
            _receiptService = receiptService;
        }

        [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.invoice != null)
            {
                return BadRequest(new List<string> { "این صورتحساب دارای مرجع می باشد"+'\n'+
                        "امکان تغییر الگو امکان پذیر نیست"});
            }
            var CheckTaxPayer = await _servTaxPayer.ExistSuccessfulorSendorpendingInvoice(invoice);
            if (invoice.PatternID != item.PatternID || invoice.CustomerID != item.CustomerID)
            {
                //----Check TaxPayer

                if (CheckTaxPayer)
                    return BadRequest(new List<string> { "این صورتحساب به سازمان ارسال شده"+'\n'+
                        "برای تغییر ،صورتحساب را ابطال/اصلاح یا برگشت بزنید"});
                else if (invoice.invoiceType == InvoiceType.BackFrmSale)
                {
                    return BadRequest(new List<string>
                    { "صورتحساب در وضعیت برگشت از فروش امکان تغییر مشتری یا الگو را ندارد"+'\n'+
                        "بهتر است صورتحساب دیگر صادر کنید" });
                }
                else if (invoice.invoiceType == InvoiceType.Repair)
                {
                    return BadRequest(new List<string>
                    { "صورتحساب در وضعیت اصلاحی امکان تغییر مشتری یا الگو را ندارد"+'\n'+
                        "بهتر است صورتحساب دیگر صادر کنید" });
                }
                else if (invoice.invoiceType != InvoiceType.Bidding
                        && invoice.invoiceType != InvoiceType.Sale && invoice.invoiceType != InvoiceType.Repair)
                {
                    return BadRequest(new List<string> { $"صورتحساب در حالت {invoice.invoiceType.GetEnumDisplayName()} نمی تواند ویرایش شود"+'\n'+
                                 $"فقط در حالت پیش نویس ، فاکتور و اصلاح (که به سازمان ارسال نشده باشد) میتوان سند را ویرایش کرد" });
                }
            }
            else if (invoice.InvoicIssueDate != item.InvoicIssueDate || invoice.InvoiceDate != item.InvoiceDate)
            {
                if (CheckTaxPayer)
                    return BadRequest(new List<string> { "این صورتحساب به سازمان ارسال شده"+'\n'+
                        "امکان تغییر تاریخ را ندارد"});
                else if (invoice.BillReference.HasValue)
                {
                    if (invoice.InvoicIssueDate != item.InvoicIssueDate && Convert.ToInt32(invoice.invoice.InvoicIssueDate) > Convert.ToInt32(item.InvoicIssueDate))
                    {
                        return BadRequest(new List<string> { "این صورتحساب مرجع دارد"+'\n'+
                       $"تاریخ صدور نمیتواند از تاریخ صدور مرجع ({invoice.invoice.InvoicIssueDate.ShamciToFormatShamci()}) کمتر باشد"});
                    }
                    if (invoice.InvoiceDate != item.InvoiceDate && Convert.ToInt32(invoice.invoice.InvoiceDate) > Convert.ToInt32(item.InvoiceDate))
                    {
                        return BadRequest(new List<string> { "این صورتحساب مرجع دارد"+'\n'+
                       $"تاریخ صورتحساب نمیتواند از تاریخ صورتحساب مرجع ({invoice.invoice.InvoiceDate.ShamciToFormatShamci()}) کمتر باشد"});
                    }
                }
            }


            //-----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()} نمی تواند ویرایش شود" });
            //}
            //if (invoice.invoiceType!=InvoiceType.Cancellation)
            //{
                //bool InvoiceHasaRemittanceBillReference = invoice.BillReference.HasValue && await _remittanceService.HasaRemittance(invoice.BillReference.Value);
                await _receiptService.DeleteByInvoiceID(invoice.ID, user.RolUsers.First().CompanyID);
                await _remittanceService.DeleteByInvoiceID(invoice.ID,user.RolUsers.First().CompanyID);
                //foreach (var item in invoice.invoiceDetails)
                //{
                //    if (await _remittanceService.HasaRemittance(invoice.ID, item.CODID))
                //    {
                //        await _receiptService.ADD(new Shared.DTOs.Warehouse.ReceiptDto()
                //        {
                //            CODID = item.CODID,
                //            Count = item.am.GetValueOrDefault(),
                //            Date = DateTime.Now.ConvertMiladiToShamsi(),
                //            ForSale = true,
                //            InvoiceID = item.InvoiceID,
                //            Type = TypeReceipt.Shopping,
                //            info = $"حذف صورتحساب {item.InvoiceID}",

                //        }, user.RolUsers.First().CompanyID, true);

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

                switch (invoiceType)
                {
                    //ابطال
                    case 3:
                        foreach (var item in Invoice.invoiceDetails)
                        {
                            if (await _remittanceService.HasaRemittance(Invoice.ID, item.CODID))
                            {
                                await _receiptService.ADD(new Shared.DTOs.Warehouse.ReceiptDto()
                                {
                                    CODID = item.CODID,
                                    Count = item.am.GetValueOrDefault(),
                                    Date = DateTime.Now.ConvertMiladiToShamsi(),
                                    ForSale = true,
                                    InvoiceID = item.InvoiceID,
                                    Type = TypeReceipt.Shopping,
                                    info = $"ابطال شدن صورتحساب {item.InvoiceID}",

                                }, user.RolUsers.First().CompanyID, true);
                            }
                        }
                        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 = DateTime.Now.ConvertMiladiToShamsi(),
                            InvoiceDate = DateTime.Now.ConvertMiladiToShamsi(),
                            LastChangeUserID = Convert.ToInt32(UserID),
                            BillReference = Invoice.ID,
                            IsDeleted = false,
                            PatternID = Invoice.PatternID,
                            setm = Invoice.setm,
                            crn = Invoice.crn,
                            CottageDateOfCustomsDeclaration = Invoice.CottageDateOfCustomsDeclaration,
                            ft = Invoice.ft,
                            cdcn = Invoice.cdcn,
                            insp = Invoice.insp,
                            billid = Invoice.billid,
                            scc = Invoice.scc,
                            scln = Invoice.scln,
                            seventeentax = Invoice.seventeentax,
                            tinc = Invoice.tinc,
                            invoiceDetails = Invoice.invoiceDetails.Select(s => new InvoiceItem
                            {
                                CODID = s.CODID,
                                am = s.am,
                                fee = s.fee,
                                dis = s.dis,
                                bros = s.bros,
                                bsrn = s.bsrn,
                                consfee = s.consfee,
                                cut = s.cut,
                                exr = s.exr,
                                nw = s.nw,
                                odam = s.odam,
                                odr = s.odr,
                                odt = s.odt,
                                olam = s.olam,
                                olr = s.olr,
                                olt = s.olt,
                                spro = s.spro,
                                sscv = s.sscv,
                                ssrv = s.ssrv,
                                pspd = s.pspd,
                                cui = s.cui,
                            }).ToList(),
                            payments = Invoice.payments.Select(s => new InvoicePayment()
                            {
                                acn = s.acn,
                                iinn = s.iinn,
                                PaymentDateTime = s.PaymentDateTime,
                                pcn = s.pcn,
                                pid = s.pid,
                                pmt = s.pmt,
                                pv = s.pv,
                                trmn = s.trmn,
                                trn = s.trn,
                            }).ToList()
                        }, false);
                        if (result > 0)
                        {
                            foreach (var item in Invoice.invoiceDetails)
                            {
                                if (await _remittanceService.HasaRemittance(Invoice.ID, item.CODID))
                                {
                                   await _remittanceService.DeleteByCODIDAndInvoiceID(Invoice.ID,item.CODID, user.RolUsers.First().CompanyID);
                                    //await _receiptService.ADD(new Shared.DTOs.Warehouse.ReceiptDto()
                                    //{
                                    //    CODID = item.CODID,
                                    //    Count = item.am.GetValueOrDefault(),
                                    //    Date = DateTime.Now.ConvertMiladiToShamsi(),
                                    //    ForSale = true,
                                    //    InvoiceID = item.InvoiceID,
                                    //    Type = TypeReceipt.Shopping,
                                    //    info = $"رسید خودکار: صورتحساب {item.InvoiceID} از {Invoice.invoiceType.GetEnumDisplayName()} به {((InvoiceType)invoiceType).GetEnumDisplayName()}",

                                    //}, user.RolUsers.First().CompanyID, true);
                                    await _remittanceService.ADD(new Shared.DTOs.Warehouse.RemittanceDto()
                                    {
                                        CODID = item.CODID,
                                        Count = item.am.GetValueOrDefault(),
                                        Date = DateTime.Now.ConvertMiladiToShamsi(),
                                        InvoiceID = result,
                                        Type = TypeRemittance.Sale,
                                        info = $"حواله خودکار: از صورتحساب {result}"
                                    });
                                }
                            }
                            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 = DateTime.Now.ConvertMiladiToShamsi(),
                            InvoiceDate = DateTime.Now.ConvertMiladiToShamsi(),
                            LastChangeUserID = Convert.ToInt32(UserID),
                            BillReference = Invoice.ID,
                            IsDeleted = false,
                            PatternID = Invoice.PatternID,
                            setm = Invoice.setm,
                            crn = Invoice.crn,
                            CottageDateOfCustomsDeclaration = Invoice.CottageDateOfCustomsDeclaration,
                            ft = Invoice.ft,
                            cdcn = Invoice.cdcn,
                            insp = Invoice.insp,
                            billid = Invoice.billid,
                            scc = Invoice.scc,
                            scln = Invoice.scln,
                            seventeentax = Invoice.seventeentax,
                            tinc = Invoice.tinc,
                            invoiceDetails = Invoice.invoiceDetails.Select(s => new InvoiceItem
                            {
                                CODID = s.CODID,
                                am = s.am,
                                fee = s.fee,
                                dis = s.dis,
                                bros = s.bros,
                                bsrn = s.bsrn,
                                consfee = s.consfee,
                                cut = s.cut,
                                exr = s.exr,
                                nw = s.nw,
                                odam = s.odam,
                                odr = s.odr,
                                odt = s.odt,
                                olam = s.olam,
                                olr = s.olr,
                                olt = s.olt,
                                spro = s.spro,
                                sscv = s.sscv,
                                ssrv = s.ssrv,
                                pspd = s.pspd,
                                cui = s.cui,
                            }).ToList(),
                            payments = Invoice.payments.Select(s => new InvoicePayment()
                            {
                                acn = s.acn,
                                iinn = s.iinn,
                                PaymentDateTime = s.PaymentDateTime,
                                pcn = s.pcn,
                                pid = s.pid,
                                pmt = s.pmt,
                                pv = s.pv,
                                trmn = s.trmn,
                                trn = s.trn,
                            }).ToList()
                        }, false);
                        if (result1 > 0)
                        {
                            foreach (var item in Invoice.invoiceDetails)
                            {
                                if (await _remittanceService.HasaRemittance(Invoice.ID, item.CODID))
                                {
                                    await _remittanceService.DeleteByCODIDAndInvoiceID(Invoice.ID, item.CODID, user.RolUsers.First().CompanyID);
                                    //await _receiptService.ADD(new Shared.DTOs.Warehouse.ReceiptDto()
                                    //{
                                    //    CODID = item.CODID,
                                    //    Count = item.am.GetValueOrDefault(),
                                    //    Date = DateTime.Now.ConvertMiladiToShamsi(),
                                    //    ForSale = true,
                                    //    InvoiceID = item.InvoiceID,
                                    //    Type = TypeReceipt.Shopping,
                                    //    info = $"رسید خودکار: صورتحساب {item.InvoiceID} از {Invoice.invoiceType.GetEnumDisplayName()} به {((InvoiceType)invoiceType).GetEnumDisplayName()}",

                                    //}, user.RolUsers.First().CompanyID, true);
                                    await _remittanceService.ADD(new Shared.DTOs.Warehouse.RemittanceDto()
                                    {
                                        CODID = item.CODID,
                                        Count = item.am.GetValueOrDefault(),
                                        Date = DateTime.Now.ConvertMiladiToShamsi(),
                                        InvoiceID = result1,
                                        Type = TypeRemittance.Sale,
                                        info = $"حواله خودکار: از صورتحساب {result1}"
                                    });
                                }
                            }
                            return Ok(await _servInvoice.GetInvoice(user.RolUsers.First().CompanyID, result1));
                        }
                        break;

                    default:
                        return BadRequest(new List<string> { $"تغییر وضعیت از {Invoice.invoiceType.GetEnumDisplayName()} به {((InvoiceType)invoiceType).GetEnumDisplayName()} امکان پذیر نیست این صورتحساب به سامانه مودیان ارسال شده" });
                }
            }
            if (Invoice.invoiceType == InvoiceType.Repair)
            {
                switch (invoiceType)
                {
                    case 3:
                        foreach (var item in Invoice.invoiceDetails)
                        {
                            if (await _remittanceService.HasaRemittance(Invoice.ID, item.CODID))
                            {
                                await _receiptService.ADD(new Shared.DTOs.Warehouse.ReceiptDto()
                                {
                                    CODID = item.CODID,
                                    Count = item.am.GetValueOrDefault(),
                                    Date = DateTime.Now.ConvertMiladiToShamsi(),
                                    ForSale = true,
                                    InvoiceID = item.InvoiceID,
                                    Type = TypeReceipt.Shopping,
                                    info = $"ابطال شدن صورتحساب {item.InvoiceID}",

                                }, user.RolUsers.First().CompanyID, true);
                            }
                        }
                        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 = DateTime.Now.ConvertMiladiToShamsi(),
                            InvoiceDate = DateTime.Now.ConvertMiladiToShamsi(),
                            LastChangeUserID = Convert.ToInt32(UserID),
                            BillReference = Invoice.ID,
                            IsDeleted = false,
                            PatternID = Invoice.PatternID,
                            setm = Invoice.setm,
                            crn = Invoice.crn,
                            CottageDateOfCustomsDeclaration = Invoice.CottageDateOfCustomsDeclaration,
                            ft = Invoice.ft,
                            cdcn = Invoice.cdcn,
                            insp = Invoice.insp,
                            billid = Invoice.billid,
                            scc = Invoice.scc,
                            scln = Invoice.scln,
                            seventeentax = Invoice.seventeentax,
                            tinc = Invoice.tinc,
                            invoiceDetails = Invoice.invoiceDetails.Select(s => new InvoiceItem
                            {
                                CODID = s.CODID,
                                am = s.am,
                                fee = s.fee,
                                dis = s.dis,
                                bros = s.bros,
                                bsrn = s.bsrn,
                                consfee = s.consfee,
                                cut = s.cut,
                                exr = s.exr,
                                nw = s.nw,
                                odam = s.odam,
                                odr = s.odr,
                                odt = s.odt,
                                olam = s.olam,
                                olr = s.olr,
                                olt = s.olt,
                                spro = s.spro,
                                sscv = s.sscv,
                                ssrv = s.ssrv,
                                pspd = s.pspd,
                                cui = s.cui,
                            }).ToList(),
                            payments = Invoice.payments.Select(s => new InvoicePayment()
                            {
                                acn = s.acn,
                                iinn = s.iinn,
                                PaymentDateTime = s.PaymentDateTime,
                                pcn = s.pcn,
                                pid = s.pid,
                                pmt = s.pmt,
                                pv = s.pv,
                                trmn = s.trmn,
                                trn = s.trn,
                            }).ToList()
                        }, false);
                        if (result2 > 0)
                        {
                            foreach (var item in Invoice.invoiceDetails)
                            {
                                if (await _remittanceService.HasaRemittance(Invoice.ID, item.CODID))
                                {
                                    await _remittanceService.DeleteByCODIDAndInvoiceID(Invoice.ID, item.CODID, user.RolUsers.First().CompanyID);
                                    //await _receiptService.ADD(new Shared.DTOs.Warehouse.ReceiptDto()
                                    //{
                                    //    CODID = item.CODID,
                                    //    Count = item.am.GetValueOrDefault(),
                                    //    Date = DateTime.Now.ConvertMiladiToShamsi(),
                                    //    ForSale = true,
                                    //    InvoiceID = item.InvoiceID,
                                    //    Type = TypeReceipt.Shopping,
                                    //    info = $"رسید خودکار: صورتحساب {item.InvoiceID} از {Invoice.invoiceType.GetEnumDisplayName()} به {((InvoiceType)invoiceType).GetEnumDisplayName()}",

                                    //}, user.RolUsers.First().CompanyID, true);
                                    await _remittanceService.ADD(new Shared.DTOs.Warehouse.RemittanceDto()
                                    {
                                        CODID = item.CODID,
                                        Count = item.am.GetValueOrDefault(),
                                        Date = DateTime.Now.ConvertMiladiToShamsi(),
                                        InvoiceID = result2,
                                        Type = TypeRemittance.Sale,
                                        info = $"حواله خودکار: از صورتحساب {result2}"
                                    });
                                }
                            }
                            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)
            {
                switch (invoiceType)
                {
                    case 3:
                        foreach (var item in Invoice.invoiceDetails)
                        {
                            if (await _remittanceService.HasaRemittance(Invoice.ID, item.CODID))
                            {
                                await _receiptService.ADD(new Shared.DTOs.Warehouse.ReceiptDto()
                                {
                                    CODID = item.CODID,
                                    Count = item.am.GetValueOrDefault(),
                                    Date = DateTime.Now.ConvertMiladiToShamsi(),
                                    ForSale = true,
                                    InvoiceID = item.InvoiceID,
                                    Type = TypeReceipt.Shopping,
                                    info = $"ابطال شدن صورتحساب {item.InvoiceID}",

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


            return NoContent();

        }
        [HttpPost("CopyInvoice/{InvoiceID}")]// ok
        public async Task<ActionResult<InvoiceDTO>> CopyInvoice(int InvoiceID)
        {
            //-----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();

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


            var result = await _servInvoice.AddInvoice(new Invoice()
            {

                Title = Invoice.Title,
                Des = Invoice.Des,
                invoiceType = InvoiceType.Bidding,
                CustomerID = Invoice.CustomerID,
                CompanyID = Invoice.CompanyID,
                InvoicIssueDate = Invoice.InvoicIssueDate.Replace("/", ""),
                InvoiceDate = Invoice.InvoicIssueDate.Replace("/", ""),
                LastChangeUserID = Convert.ToInt32(UserID),
                IsDeleted = false,
                PatternID = Invoice.PatternID,
                setm = Invoice.setm,
                crn = Invoice.crn,
                CottageDateOfCustomsDeclaration = Invoice.CottageDateOfCustomsDeclaration,
                ft = Invoice.ft,
                cdcn = Invoice.cdcn,
                insp = Invoice.insp,
                billid = Invoice.billid,
                scc = Invoice.scc,
                scln = Invoice.scln,
                seventeentax = Invoice.seventeentax,
                tinc = Invoice.tinc,
                invoiceDetails = Invoice.invoiceDetails.Select(s => new InvoiceItem
                {
                    CODID = s.CODID,
                    am = s.am,
                    fee = s.fee,
                    dis = s.dis,
                    bros = s.bros,
                    bsrn = s.bsrn,
                    consfee = s.consfee,
                    cut = s.cut,
                    exr = s.exr,
                    nw = s.nw,
                    odam = s.odam,
                    odr = s.odr,
                    odt = s.odt,
                    olam = s.olam,
                    olr = s.olr,
                    olt = s.olt,
                    spro = s.spro,
                    sscv = s.sscv,
                    ssrv = s.ssrv,
                    pspd = s.pspd,
                    cui = s.cui,
                }).ToList(),
                payments = Invoice.payments.Select(s => new InvoicePayment()
                {
                    acn = s.acn,
                    iinn = s.iinn,
                    PaymentDateTime = s.PaymentDateTime,
                    pcn = s.pcn,
                    pid = s.pid,
                    pmt = s.pmt,
                    pv = s.pv,
                    trmn = s.trmn,
                    trn = s.trn,
                }).ToList()
            }, true);
            if (result > 0)
                return Ok(await _servInvoice.GetInvoice(user.RolUsers.First().CompanyID, result));


            return NoContent();

        }
        [HttpGet("GetPatterns")]
        public async Task<ActionResult<List<IdName<int>>>> GetPatterns()
        {
            return Ok(await _servTaxPayer.GetPatterns());
        }
        [HttpGet("GetReport/{InvoiceID}")]
        public async Task<ActionResult<string>> GetReport(int InvoiceID)
        {
            //-----GetUserAndCompany
            var claim = HttpContext.User.Claims.First(c => c.Type == "UserID");
            var UserID = claim.Value;
            var user = await _servUser.GetUserByUserID(Convert.ToInt32(UserID));

            var CompanyID = user?.RolUsers.First().CompanyID;

            if (!await _servInvoice.ExistInvoiceByInvoiceID(CompanyID.Value, InvoiceID))
                return NotFound();

            var result = await _servInvoice.GetInvoice(user.RolUsers.First().CompanyID, InvoiceID);

            string base64 = await _servReport.CreateImage(result, user?.RolUsers.First().Company.Logo == null ? "" : Convert.ToBase64String(user?.RolUsers.First().Company.Logo), user?.RolUsers.First().Company.Name);
            return Ok(base64);
        }
        [HttpPost("IssuingRemittance/{InvoiceID}")]
        public async Task<ActionResult<string>> IssuingRemittance(int InvoiceID)
        {
            //-----GetUserAndCompany
            var claim = HttpContext.User.Claims.First(c => c.Type == "UserID");
            var UserID = claim.Value;
            var user = await _servUser.GetUserByUserID(Convert.ToInt32(UserID));

            var CompanyID = user?.RolUsers.First().CompanyID;

            if (!await _servInvoice.ExistInvoiceByInvoiceID(CompanyID.Value, InvoiceID))
                return NotFound();

            if (await _remittanceService.HasaRemittance(InvoiceID))
            {
                return BadRequest(new List<string>() { "این صورتحساب حواله دارد" });
            }
            else
            {

                if (_servInvoice.checkFatherInvoiceByInvoiceID(user.RolUsers.First().CompanyID, InvoiceID).Result)
                    return BadRequest(new List<string> {"این صورتحساب، مرجع چند صورتحساب دیگر می باشد " +'\n'+'\r'+
                          "نمیتواند برای این صورتحساب حواله صادر کنید، ابتدا صورتحساب هایی که ارتباط دارند را حذف کنید" });

                List<string> errors = new List<string>();
                var result = await _servInvoice.GetInvoice(user.RolUsers.First().CompanyID, InvoiceID);
                if (result.invoiceType == InvoiceType.Bidding || result.invoiceType == InvoiceType.Cancellation)
                {
                    return BadRequest(new List<string>() { $"در وضعیت {result.invoiceType.GetEnumDisplayName()} امکان صدور حواله ممکن نیست" });
                }
                //check
                foreach (var item in result.items
                    .GroupBy(i => i.CODID).Select(g => new { CODID = g.Key, TotalAm = g.Sum(i => i.am) }))
                {
                    var Inventory = await _warehouseService.Inventory(CompanyID.Value, item.CODID);
                    if (Inventory - item.TotalAm < 0)
                    {
                        errors.Add($"موجودی کالا {result.items.First(w => w.CODID == item.CODID).sstt} کمتر از درخواست شماست");
                    }
                }
                if (errors.Count == 0)
                {
                    //save
                    await _remittanceService.AddRange(result.items.Select(s => new Data.Models.Warehouse.Remittance()
                    {
                        CODID = s.CODID,
                        Count = s.am,
                        Date = DateTime.Now.ConvertMiladiToShamsi(),
                        info = $"حواله خودکار از صورتحساب {InvoiceID}",
                        Type = TypeRemittance.Sale,
                        InvoiceID = InvoiceID,
                        Deleted = false,
                        CreateDt=DateTime.Now
                    }).ToList());
                    return Ok();
                }
                else
                {
                    return BadRequest(errors);
                }



            }



        }
        [HttpPost("FreeRemittance/{InvoiceID}")]
        public async Task<ActionResult> FreeRemittance(int InvoiceID)
        {
            //-----GetUserAndCompany
            var claim = HttpContext.User.Claims.First(c => c.Type == "UserID");
            var UserID = claim.Value;
            var user = await _servUser.GetUserByUserID(Convert.ToInt32(UserID));

            var CompanyID = user?.RolUsers.First().CompanyID;

            if (!await _servInvoice.ExistInvoiceByInvoiceID(CompanyID.Value, InvoiceID))
                return NotFound();

           
            await _receiptService.DeleteByInvoiceID(InvoiceID, CompanyID.Value);
            await _remittanceService.DeleteByInvoiceID(InvoiceID, CompanyID.Value);

            return Ok();    
            //return BadRequest(new List<string>() { $"حواله ای یافت نشد" });


        }
        [HttpGet("HasaRemittance/{InvoiceID}")]
        public async Task<ActionResult> HasaRemittance(int InvoiceID)
        {

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

            var CompanyID = user?.RolUsers.First().CompanyID;

            if (!await _servInvoice.ExistInvoiceByInvoiceID(CompanyID.Value, InvoiceID))
                return NotFound();

            if (await _remittanceService.HasaRemittance(InvoiceID))
                return NotFound();
            return Ok();
        }
    }
}
