using Back.Common;
using Back.Data.Contracts;
using Back.Data.Models;
using Back.Services;
using Back.Validations;
using FluentValidation;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Shared.DTOs;
using System.Net;
using System.Runtime.ConstrainedExecution;
using System.Security.Cryptography;
using static Shared.DTOs._TaxPayer;

namespace Back.Controllers
{
    [Route("api/[controller]")]
    [Authorize]
    [ApiController]
    public class InvoicePaymentController : ControllerBase
    {
        private readonly servInvoicePayment _servpay;
        private readonly servUser _servUser;
        private readonly AUInvoicePayValidation _validation;
        private readonly servInvoice _servInvoice;
        public InvoicePaymentController(servInvoicePayment servpay, AUInvoicePayValidation validation
            , servUser servUser, servInvoice servInvoice)
        {
            _servpay = servpay;
            _validation = validation;
            _servUser = servUser;
            _servInvoice = servInvoice;

        }
        [HttpGet("PaymentMethods")]
        public async Task<ActionResult<List<IdName<string>>>> PaymentMethods()
        {
            return Ok(await _servpay.GetPaymentMethods());
        }
        [HttpPost("AddPay")]
        public async Task<ActionResult<InvoicePaymentDTO>> AddItem([FromBody] InvoiceItemAction<InvoicePaymentDTO> model)
        {
            //-----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 _validation.ValidateAsync(Tuple.Create(user.RolUsers.First().CompanyID, model.invoiceID, model.item, eActionValidation.add));
            if (!resultValidationmodel.IsValid)
                return BadRequest(resultValidationmodel.Errors.Select(s => s.ErrorMessage).ToList());

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

            //-------------pmt
            List<Back.Data.Models.Coding> codings  = await _servInvoice.GetCodingPMT();
            //-----------------------

            invoice.LastChangeUserID = Convert.ToInt32(UserID);

            if (await _servInvoice.UpdateInvoice(invoice))
            {
                var item = await _servpay.Add(new Data.Models.InvoicePayment
                {
                    InvoiceID = model.invoiceID,
                    acn = model.item.acn,
                    iinn = model.item.iinn,
                    PaymentDateTime = model.item.PaymentDateTime.Replace("/", ""),
                    pcn = model.item.pcn,
                    pid = model.item.pid,
                    pmt = model.item.pmt,
                    pv = model.item.pv,
                    trmn = model.item.trmn,
                    trn = model.item.trn,


                });
                return Ok(item!=null ?new InvoicePaymentDTO
                {
                    ID = item.ID,
                    acn = item.acn,
                    iinn = item.iinn,
                    pcn = item.pcn,
                    PaymentDateTime = item.PaymentDateTime.ShamciToFormatShamci(),
                    pid = item.pid,
                    pmt = item.pmt,
                    pv = item.pv,
                    trmn = item.trmn,
                    trn = item.trn,
                    paymentMethod = item.pmt.HasValue ? codings.Where(w => w.Code == item.pmt.Value.ToString()).Select(s => s.Title).FirstOrDefault() : null,
                } :null);
            }
            else return BadRequest(new List<string> { "خطایی رخ داده" });


        }
        [HttpPut("UpdatePay")]
        public async Task<ActionResult<bool>> UpdateItem([FromBody] InvoiceItemAction<InvoicePaymentDTO> model)
        {
            //-----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, model.invoiceID);
            if (invoice == null)
                return BadRequest(new List<string> { "invoice notFound..." });



            //-----Validaton
            var resultValidationmodel = await _validation.ValidateAsync(Tuple.Create(user.RolUsers.First().CompanyID, model.invoiceID, model.item, eActionValidation.update));
            if (!resultValidationmodel.IsValid)
            {
                if (invoice.invoiceType != InvoiceType.BackFrmSale || (invoice.invoiceType != InvoiceType.BackFrmSale
                    && resultValidationmodel.Errors.Count > 1))
                {
                    return BadRequest(resultValidationmodel.Errors.Select(s => s.ErrorMessage).ToList());
                }

            }





            var item = await _servpay.GetInvoicePayByInvoicePayID(user.RolUsers.First().CompanyID, model.invoiceID, model.item.ID.Value);
            if (item == null)
                return BadRequest(new List<string> { "invoice Pay notFound..." });


            invoice.LastChangeUserID = Convert.ToInt32(UserID);

            item.acn = model.item.acn;
            item.iinn = model.item.iinn;
            item.PaymentDateTime = model.item.PaymentDateTime.Replace("/", "");
            item.pcn = model.item.pcn;
            item.pid = model.item.pid;
            item.pmt = model.item.pmt;
            item.pv = model.item.pv;
            item.trmn = model.item.trmn;
            item.trn = model.item.trn;

            if (await _servInvoice.UpdateInvoice(invoice))
            {
                var modelout = await _servpay.Update(item);

                //-------------pmt
                List<Back.Data.Models.Coding> codings = await _servInvoice.GetCodingPMT();
                //-----------------------

                return Ok(modelout!=null ? new InvoicePaymentDTO
                {
                    ID = modelout.ID,
                    acn = modelout.acn,
                    iinn = modelout.iinn,
                    pcn = modelout.pcn,
                    PaymentDateTime = modelout.PaymentDateTime.ShamciToFormatShamci(),
                    pid = modelout.pid,
                    pmt = modelout.pmt,
                    pv = modelout.pv,
                    trmn = modelout.trmn,
                    trn = modelout.trn,
                    paymentMethod = modelout.pmt.HasValue ? codings.Where(w => w.Code == modelout.pmt.Value.ToString()).Select(s => s.Title).FirstOrDefault() : null,
                } : null);
            }
               

            else
                return BadRequest(new List<string> { "خطایی رخ داده" });


        }
        [HttpDelete("DeletePay/{InvoicePayID}")]
        public async Task<ActionResult<bool>> DeleteItem(int InvoicePayID)
        {

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

            //-----Get invoicePay
            var payitem = await _servpay.GetinvoicePay(user.RolUsers.First().CompanyID, InvoicePayID);
            if (payitem == null)
                return NotFound(new List<string> { "invoice pay notFound..." });

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



            payitem.invoice.LastChangeUserID = Convert.ToInt32(UserID);



            if (await _servInvoice.UpdateInvoice(payitem.invoice))
                return Ok(await _servpay.Delete(payitem));

            else return BadRequest(new List<string> { "خطایی رخ داده" });


        }


    }
}
