using Back.Common;
using Back.Data.Models;
using Back.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using Org.BouncyCastle.Asn1.Cmp;
using Org.BouncyCastle.Ocsp;
using Shared.DTOs;
using Shared.DTOs.Serch;
using System;
using System.Security.Cryptography;
using TaxCollectData.Library.Dto.Content;
using static Shared.DTOs._TaxPayer;
using static System.Collections.Specialized.BitVector32;

namespace Back.Controllers
{
    [Route("api/[controller]")]
    [Authorize]
    [ApiController]
    public class TaxPayerController : ControllerBase
    {
        private readonly servTaxPayer _servTaxPayer;
        private readonly servUser _servUser;
        private readonly ActionTaxPayer _actionTaxPayer;
        public TaxPayerController(servTaxPayer servTaxPayer, servUser servUser, ActionTaxPayer actionTaxPayer)
        {
            _servTaxPayer = servTaxPayer;
            _servUser = servUser;
            _actionTaxPayer = actionTaxPayer;
        }
        [HttpGet("GetInvoice/{ID}")]
        public async Task<ActionResult<_TaxPayer.Atemplatefield?>> Get(int ID)
        {
            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 _servTaxPayer.GetInvoice(user.RolUsers.First().CompanyID, ID);
            if (result == null)
                return BadRequest(new List<string> { "صورتحساب یافت نشد" });

            else
            {
                if (!result.PatternID.HasValue || result.PatternID==0)
                    return BadRequest(new List<string> { "ابتدا برای این صورتحساب الگو در نظر بگیرید" });

                if (result.invoiceType == InvoiceType.Bidding)
                    return BadRequest(new List<string> { "صورتحساب در وضعیت پیش نویس نمیتواند ارسال شود" });

                if (await _servTaxPayer.ExistSuccessfulorSendorpendingInvoice(result))
                    return BadRequest(new List<string> { "این صورتحساب قبلا به سازمان ارسال شده" });

                if ((result.invoiceType == InvoiceType.BackFrmSale || result.invoiceType == InvoiceType.Repair)
                    && !result.BillReference.HasValue)
                    return BadRequest(new List<string> { "در وضعیت برگشت از فروش و اصلاحی باید صورتحساب مرجع وجود داشته باشد" });


                if ((result.invoiceType == InvoiceType.BackFrmSale || result.invoiceType == InvoiceType.Repair)
                    && !await _servTaxPayer.ExistSuccessfulorSendorpendingInvoice(result.invoice))
                    return BadRequest(new List<string> { "در وضعیت برگشت از فروش و اصلاحی باید صورتحساب مرجع به سامانه مودیان ارسال شده باشد" });



                return Ok(await _servTaxPayer.GetFildInvoiceForPreparation(result));
            }

        }
        [HttpPost("PreparationInvoiceBeforeSending")]
        public async Task<ActionResult<bool>> PreparationInvoiceBeforeSending([FromBody] Atemplatefield item)
        {
            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 _servTaxPayer.GetInvoice(user.RolUsers.First().CompanyID, item.header.ID);
            if (result == null)
                return BadRequest(new List<string> { "صورتحساب یافت نشد" });


            return Ok(await _servTaxPayer.PreparationInvoiceBeforeSending(item, result));
        }
        [HttpGet("CheckAuth")]
        public async Task<ActionResult<bool>> CheckAuth()
        {

            var claim = HttpContext.User.Claims.First(c => c.Type == "UserID");
            var UserID = claim.Value;
            var user = await _servUser.GetUserByUserID(Convert.ToInt32(UserID));
            if (await _actionTaxPayer.login(user.RolUsers.First().CompanyID))
                return Ok();

            return BadRequest();

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

            var claim = HttpContext.User.Claims.First(c => c.Type == "UserID");
            var UserID = claim.Value;
            var user = await _servUser.GetUserByUserID(Convert.ToInt32(UserID));
            if (!await _actionTaxPayer.login(user.RolUsers.First().CompanyID))
                return BadRequest(new List<string> { "خطا در احراز هویت سازمان مالیاتی" });

            var result = await _servTaxPayer.GetInvoice(user.RolUsers.First().CompanyID, InvoiceID);
            if (result == null)
                return BadRequest(new List<string> { "صورتحساب یافت نشد" });

            else
            {
                if (!result.PatternID.HasValue)
                    return BadRequest(new List<string> { "ابتدا برای این صورتحساب الگو در نظر بگیرید" });

                if (result.invoiceType == InvoiceType.Bidding)
                    return BadRequest(new List<string> { "صورتحساب در وضعیت پیش نویس نمیتواند ارسال شود" });

                if (await _servTaxPayer.ExistSuccessfulorSendorpendingInvoice(result))
                    return BadRequest(new List<string> { "این صورتحساب قبلا به سازمان ارسال شده" });

                if ((result.invoiceType == InvoiceType.BackFrmSale || result.invoiceType == InvoiceType.Repair)
                    && !result.BillReference.HasValue)
                    return BadRequest(new List<string> { "در وضعیت برگشت از فروش و اصلاحی باید صورتحساب مرجع وجود داشته باشد" });


                if ((result.invoiceType == InvoiceType.BackFrmSale || result.invoiceType == InvoiceType.Repair)
                    && !await _servTaxPayer.ExistSuccessfulorSendorpendingInvoice(result.invoice))
                    return BadRequest(new List<string> { "در وضعیت برگشت از فروش و اصلاحی باید صورتحساب مرجع به سامانه مودیان ارسال شده باشد" });

                #region Inital Send
                InvoiceHeaderDto header = new InvoiceHeaderDto();
                #region header
                if (header.Inty == 1 && header.Inp == 1)
                    header = new InvoiceHeaderDto
                    {
                        //نوع شخص خریدار
                        Tob = result.tob,
                        // صورتحساب نوع *
                        Inty = result.inty ?? 1,
                        //الگوی صورتحساب *
                        Inp = result.inp ?? 1,
                        //موضوع صورتحساب * 
                        Ins = result.ins ?? 1,
                        //شماره منحصر به فرد مالیاتی
                        Taxid = _actionTaxPayer.GenerateTaxid(result.inno, result.InvoiceDate.Replace("/", "").Trim()),
                        //سریال صورت حساب
                        Inno = result.inno ?? null,
                        //شماره اقتصادی فروشنده به جاش شناسه ملی داده شد
                        Tins = result.tins ?? null,
                        //مجموع مبلغ قبل از کسر تخفیف
                        Tprdis = result.tprdis ?? null,
                        //  مجموع مبلغ پس از کسر تخفیف
                        Tadis = result.tadis ?? null,
                        //مجموع مالیات بر ارزش افزوده
                        Tvam = result.tvam ?? null,
                        // مجموع سایر مالیات، عوارض و وجوه قانونی
                        Todam = result.todam ?? null,
                        //صورتحساب مجموع
                        Tbill = result.tbill ?? null,
                        // تسویه روش 
                        Setm = result.setm ?? null,
                        //نقدی پرداختی مبلغ
                        Cap = result.cap ?? null,
                        //پرداختی نسیه
                        Insp = result.insp ?? null,
                        //مجموع تخفیفات
                        Tdis = result.tdis ?? null,
                        //شماره منحصر به فرد مالیاتی صورتحساب مرجع
                        Irtaxid = result.invoiceType == InvoiceType.BackFrmSale || result.invoiceType == InvoiceType.Repair ? result.invoice.taxid : null,
                        //شماره اقتصادی خریدار
                        Tinb = result.tinb ?? null,
                        //زمان صدور
                        Indatim = result.indatim ?? null,
                        //زمان ایجاد
                        Indati2m = result.Indati2m ?? null,
                        //کد شعبه خریدار
                        Bbc = result.bbc ?? null,
                        Tvop = result.tvop ?? null,
                        Crn = result.crn ?? null,
                        Tax17 = string.IsNullOrEmpty(result.seventeentax) ? null : Convert.ToDecimal(result.seventeentax),
                        Scc = result.scc ?? null,
                        Scln = result.scln ?? null,
                        Bid = result.bid ?? null,
                    };
                if (header.Inty == 1 && header.Inp == 2)
                    header = new InvoiceHeaderDto
                    {
                        //نوع شخص خریدار
                        Tob = result.tob,
                        // صورتحساب نوع *
                        Inty = result.inty ?? 1,
                        //الگوی صورتحساب *
                        Inp = result.inp ?? 1,
                        //موضوع صورتحساب * 
                        Ins = result.ins ?? 1,
                        //شماره منحصر به فرد مالیاتی
                        Taxid = _actionTaxPayer.GenerateTaxid(result.inno, result.InvoiceDate.Replace("/", "").Trim()),
                        //سریال صورت حساب
                        Inno = result.inno ?? null,
                        //شماره اقتصادی فروشنده به جاش شناسه ملی داده شد
                        Tins = result.tins ?? null,
                        //مجموع مبلغ قبل از کسر تخفیف
                        Tprdis = result.tprdis ?? null,
                        //  مجموع مبلغ پس از کسر تخفیف
                        Tadis = result.tadis ?? null,
                        //مجموع مالیات بر ارزش افزوده
                        Tvam = result.tvam ?? null,
                        // مجموع سایر مالیات، عوارض و وجوه قانونی
                        Todam = result.todam ?? null,
                        //صورتحساب مجموع
                        Tbill = result.tbill ?? null,
                        // تسویه روش 
                        Setm = result.setm ?? null,
                        //نقدی پرداختی مبلغ
                        Cap = result.cap ?? null,
                        //پرداختی نسیه
                        Insp = result.insp ?? null,
                        //مجموع تخفیفات
                        Tdis = result.tdis ?? null,
                        //شماره منحصر به فرد مالیاتی صورتحساب مرجع
                        Irtaxid = result.invoiceType == InvoiceType.BackFrmSale || result.invoiceType == InvoiceType.Repair ? result.invoice.taxid : null,
                        //شماره اقتصادی خریدار
                        Tinb = result.tinb ?? null,
                        //زمان صدور
                        Indatim = result.indatim ?? null,
                        //زمان ایجاد
                        Indati2m = result.Indati2m ?? null,
                        //کد شعبه خریدار
                        Bbc = result.bbc ?? null,
                        Tvop = result.tvop ?? null,
                        Crn = result.crn ?? null,
                        Tax17 = string.IsNullOrEmpty(result.seventeentax) ? null : Convert.ToDecimal(result.seventeentax),
                        Scc = result.scc ?? null,
                        Scln = result.scln ?? null,
                        Bpn = result.bpn ?? null,
                        Bid = result.bid ?? null,
                    };
                if (header.Inty == 1 && header.Inp == 3)
                    header = new InvoiceHeaderDto
                    {
                        //نوع شخص خریدار
                        Tob = result.tob,
                        // صورتحساب نوع *
                        Inty = result.inty ?? 1,
                        //الگوی صورتحساب *
                        Inp = result.inp ?? 1,
                        //موضوع صورتحساب * 
                        Ins = result.ins ?? 1,
                        //شماره منحصر به فرد مالیاتی
                        Taxid = _actionTaxPayer.GenerateTaxid(result.inno, result.InvoiceDate.Replace("/", "").Trim()),
                        //سریال صورت حساب
                        Inno = result.inno ?? null,
                        //شماره اقتصادی فروشنده به جاش شناسه ملی داده شد
                        Tins = result.tins ?? null,
                        //مجموع مبلغ قبل از کسر تخفیف
                        Tprdis = result.tprdis ?? null,
                        //  مجموع مبلغ پس از کسر تخفیف
                        Tadis = result.tadis ?? null,
                        //مجموع مالیات بر ارزش افزوده
                        Tvam = result.tvam ?? null,
                        // مجموع سایر مالیات، عوارض و وجوه قانونی
                        Todam = result.todam ?? null,
                        //صورتحساب مجموع
                        Tbill = result.tbill ?? null,
                        // تسویه روش 
                        Setm = result.setm ?? null,
                        //نقدی پرداختی مبلغ
                        Cap = result.cap ?? null,
                        //پرداختی نسیه
                        Insp = result.insp ?? null,
                        //مجموع تخفیفات
                        Tdis = result.tdis ?? null,
                        //شماره منحصر به فرد مالیاتی صورتحساب مرجع
                        Irtaxid = result.invoiceType == InvoiceType.BackFrmSale || result.invoiceType == InvoiceType.Repair ? result.invoice.taxid : null,
                        //شماره اقتصادی خریدار
                        Tinb = result.tinb ?? null,
                        //زمان صدور
                        Indatim = result.indatim ?? null,
                        //زمان ایجاد
                        Indati2m = result.Indati2m ?? null,
                        //کد شعبه خریدار
                        Bbc = result.bbc ?? null,
                        Tvop = result.tvop ?? null,
                        Crn = result.crn ?? null,
                        Tax17 = string.IsNullOrEmpty(result.seventeentax) ? null : Convert.ToDecimal(result.seventeentax),
                        Bid = result.bid ?? null,
                    };
                #endregion header
                List<InvoiceBodyDto> InvoiceBody = new List<InvoiceBodyDto>();
                foreach (var bitem in result.invoiceDetails)
                {
                    InvoiceBodyDto item = new InvoiceBodyDto();
                    #region body    
                    if (header.Inty == 1 && header.Inp == 1)
                        item = new InvoiceBodyDto
                        {
                            //شناسه کالا / خدمت
                            Sstid = bitem.sstid,
                            //شرح کاال/خدمت
                            Sstt = bitem.sstt,
                            //واحد اندازه گیری
                            Mu = bitem.mu,
                            // تعداد
                            Am = bitem.am,
                            // مبلغ واحد
                            Fee = bitem.fee,
                            //مبلغ قبل از تخفیف
                            Prdis = bitem.prdis,
                            //مبلغ تخفیف
                            Dis = bitem.dis,
                            //مبلغ بعد از تخفیف
                            Adis = bitem.adis,
                            //نرخ مالیات بر ارزش افزوده
                            Vra = bitem.vra,
                            //مبلغ مالیات بر ارزش افزوده
                            Vam = bitem.vam,
                            // مبلغ کل کالا / خدمت
                            Tsstam = bitem.tsstam,
                            Cfee = bitem.cfee,
                            Cut = bitem.cut,
                            Exr = bitem.exr,
                            Odt = bitem.odt,
                            Odr = bitem.odr,
                            Odam = bitem.odam,
                            Olt = bitem.olt,
                            Olr = bitem.olr,
                            Olam = bitem.olam,
                            Cop = bitem.cop,
                            Vop = bitem.vop,
                            Bsrn = bitem.bsrn,


                        };

                    else if (header.Inty == 1 && header.Inp == 2)
                        item = new InvoiceBodyDto
                        {
                            //شناسه کالا / خدمت
                            Sstid = bitem.sstid,
                            //شرح کاال/خدمت
                            Sstt = bitem.sstt,
                            //واحد اندازه گیری
                            Mu = bitem.mu,
                            // تعداد
                            Am = bitem.am,
                            // مبلغ واحد
                            Fee = bitem.fee,
                            //مبلغ قبل از تخفیف
                            Prdis = bitem.prdis,
                            //مبلغ تخفیف
                            Dis = bitem.dis,
                            //مبلغ بعد از تخفیف
                            Adis = bitem.adis,
                            //نرخ مالیات بر ارزش افزوده
                            Vra = bitem.vra,
                            //مبلغ مالیات بر ارزش افزوده
                            Vam = bitem.vam,
                            // مبلغ کل کالا / خدمت
                            Tsstam = bitem.tsstam,
                            Cfee = bitem.cfee,
                            Cut = bitem.cut,
                            Exr = bitem.exr,
                            Odt = bitem.odt,
                            Odr = bitem.odr,
                            Odam = bitem.odam,
                            Olt = bitem.olt,
                            Olr = bitem.olr,
                            Olam = bitem.olam,
                            Cop = bitem.cop,
                            Vop = bitem.vop,
                            Bsrn = bitem.bsrn,


                        };

                    else if (header.Inty == 1 && header.Inp == 3)
                        item = new InvoiceBodyDto
                        {
                            //شناسه کالا / خدمت
                            Sstid = bitem.sstid,
                            //شرح کاال/خدمت
                            Sstt = bitem.sstt,
                            //واحد اندازه گیری
                            Mu = bitem.mu,
                            // تعداد
                            Am = bitem.am,
                            // مبلغ واحد
                            Fee = bitem.fee,
                            //مبلغ قبل از تخفیف
                            Prdis = bitem.prdis,
                            //مبلغ تخفیف
                            Dis = bitem.dis,
                            //مبلغ بعد از تخفیف
                            Adis = bitem.adis,
                            //نرخ مالیات بر ارزش افزوده
                            Vra = bitem.vra,
                            //مبلغ مالیات بر ارزش افزوده
                            Vam = bitem.vam,
                            // مبلغ کل کالا / خدمت
                            Tsstam = bitem.tsstam,
                            Cfee = bitem.cfee,
                            Cut = bitem.cut,
                            Exr = bitem.exr,
                            Odt = bitem.odt,
                            Odr = bitem.odr,
                            Odam = bitem.odam,
                            Olt = bitem.olt,
                            Olr = bitem.olr,
                            Olam = bitem.olam,
                            Cop = bitem.cop,
                            Vop = bitem.vop,
                            Bsrn = bitem.bsrn,
                            Consfee = bitem.consfee,
                            Spro = bitem.spro,
                            Bros = bitem.bros,
                            Tcpbs = bitem.tcpbs,
                        };

                    #endregion
                    InvoiceBody.Add(item);
                }

                var responseModel = await _actionTaxPayer.SendInvoice(user.RolUsers.First().CompanyID, header, InvoiceBody, new PaymentDto { });
                if (responseModel == null)
                {
                    return BadRequest(new List<string> { "خطا در ورود به سامانه مودیان" });
                }
                else if (responseModel.Status == 200 && (responseModel.Body.Errors == null || responseModel.Body.Errors.Count == 0))
                {
                    foreach (var item in responseModel.Body.Result)
                    {
                        var ressenttax = new SentTax
                        {
                            InvoiceID = result.ID,
                            Date = DateTime.Now.ConvertMiladiToShamsi(),
                            Time = $"{DateTime.Now.Hour}:{DateTime.Now.Minute}:{DateTime.Now.Second}",
                            InvoiceType = result.invoiceType,
                            ReferenceNumber = item.ReferenceNumber,
                            uId = item.Uid,
                            SentStatus = SentStatus.Send,
                            InvoiceModel = JsonConvert.SerializeObject(result),
                            ResponseModel = JsonConvert.SerializeObject(responseModel)
                        };
                        await _servTaxPayer.AddSentTax(ressenttax);
                    }
                    result.taxid = header.Taxid;
                    result.irtaxid = header.Irtaxid;
                    return Ok(await _servTaxPayer.UpdateInvoice(result));
                }
                else
                {
                    string errors = "";
                    foreach (var item in responseModel.Body.Errors)
                        errors += '\n' + $"{item.ErrorCode}:{item.Detail}";

                    return BadRequest(new List<string> { errors });
                }


                #endregion


            }
        }
        [HttpPost("GetAllSentTax")]
        public async Task<ActionResult<PagingDto<SentTaxDto>>> GetSentTax([FromBody] ItemSerchGetSentTax item)
        {
            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 _servTaxPayer.GetSentTax(user.RolUsers.First().CompanyID, item));
        }
        [HttpGet("GetResult/{ID}")]
        public async Task<ActionResult<DataInSendTaxDto>> GetResultByUid(int ID)
        {
            try
            {
                var claim = HttpContext.User.Claims.First(c => c.Type == "UserID");
                var UserID = claim.Value;
                var user = await _servUser.GetUserByUserID(Convert.ToInt32(UserID));
                var item = await _servTaxPayer.GetSentTax(user.RolUsers.First().CompanyID, ID);
                if (item == null)
                    return BadRequest(new List<string> { "یافت نشد" });

                if (string.IsNullOrEmpty(item.uId))
                    return BadRequest(new List<string> { "کد پیگیری یافت نشد" });

                if (!await _actionTaxPayer.login(user.RolUsers.First().CompanyID))
                    return BadRequest(new List<string> { "خطا در احراز هویت سازمان مالیاتی" });

                DataInSendTaxDto desData = new DataInSendTaxDto();
                if (item.SentStatus==SentStatus.Send
                    || item.SentStatus == SentStatus.pending
                    || item.SentStatus == SentStatus.IN_PROGRESS)
                {
           

                    var result = await _actionTaxPayer.GetResultByUid(user.RolUsers.First().CompanyID, item.uId);
                    if (result == null)
                        return BadRequest(new List<string> { "پاسخی از سازمان دریافت نشد" });

                    else
                    {
                        item.InquiryResultModel = JsonConvert.SerializeObject(result);
                        if (result.Data != null)
                        {
                            desData = JsonConvert.DeserializeObject<DataInSendTaxDto>(result.Data.ToString());
                            if (desData == null)
                            {
                                desData = new DataInSendTaxDto();
                                desData.error = JsonConvert.DeserializeObject<List<MessageInSendTaxDto>>(result.Data.ToString());
                            }
                        }
                        desData.SentStatus = item.SentStatus =
                            result.Status == "FAILED" ? SentStatus.Unsuccessful
                            : result.Status == "PENDING" ? SentStatus.pending
                            : result.Status == "SUCCESS" ? SentStatus.Successful
                            : result.Status == "NOT_FOUND" ? SentStatus.NOT_FOUND
                            : result.Status == "IN_PROGRESS" ? SentStatus.IN_PROGRESS
                            : SentStatus.Unknown;
                    }
                    if (await _servTaxPayer.UpdateSentTax(item)) return Ok(desData);

                    else return BadRequest(new List<string> { "خطای در ذخیره سازی" });
                }
                else if (item.SentStatus == SentStatus.Unsuccessful && !string.IsNullOrEmpty(item.InquiryResultModel))
                {
                    InquiryResultModel inquiryResult = JsonConvert.DeserializeObject<InquiryResultModel>(item.InquiryResultModel);
                    if (inquiryResult.Data != null)
                    {
                        desData.SentStatus = item.SentStatus =
                          inquiryResult.Status == "FAILED" ? SentStatus.Unsuccessful
                          : inquiryResult.Status == "PENDING" ? SentStatus.pending
                          : inquiryResult.Status == "SUCCESS" ? SentStatus.Successful
                          : inquiryResult.Status == "NOT_FOUND" ? SentStatus.NOT_FOUND
                          : inquiryResult.Status == "IN_PROGRESS" ? SentStatus.IN_PROGRESS
                          : SentStatus.Unknown;

                        desData = JsonConvert.DeserializeObject<DataInSendTaxDto>(inquiryResult.Data.ToString());
                        if (desData == null)
                        {
                            desData = new DataInSendTaxDto();
                            desData.error = JsonConvert.DeserializeObject<List<MessageInSendTaxDto>>(inquiryResult.Data.ToString());
                        }
                    }
                    return Ok(desData);
                }

                return BadRequest(new List<string> { "در این وضعیت امکان پذیر نمی باشد" });
            }
            catch (Exception ex)
            {
                return BadRequest(new List<string> { "خطای ناشناخته" });
            }
        }
    }
}
