using System.ComponentModel.DataAnnotations;
using EnotaryoPH.Data;
using EnotaryoPH.Data.Constants;
using EnotaryoPH.Data.Entities;
using Exadel.Compreface.Clients.CompreFaceClient;
using Exadel.Compreface.DTOs.FaceVerificationDTOs.FaceVerification;
using Exadel.Compreface.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace EnotaryoPH.Web.Pages.Principal.NotaryoSteps
{
    public class TakeSelfieModel : PageModel
    {
        private readonly NotaryoDBContext _notaryoDBContext;
        private readonly ICurrentUserService _currentUserService;
        private readonly ICompreFaceClient _compreFaceClient;
        private readonly IConfiguration _configuration;

        public TakeSelfieModel(NotaryoDBContext notaryoDBContext, ICurrentUserService currentUserService, ICompreFaceClient compreFaceClient, IConfiguration configuration)
        {
            _notaryoDBContext = notaryoDBContext;
            _currentUserService = currentUserService;
            _compreFaceClient = compreFaceClient;
            _configuration = configuration;
        }

        public void OnGet()
        {
        }

        public async Task<IActionResult> OnPostAsync()
        {
            if (!ModelState.IsValid)
            {
                return Page();
            }

            var user = _notaryoDBContext.Users.FirstOrDefault(u => u.User_UID == _currentUserService.GetUser_UID());

            TransactionSelfie selfieEntity;
            if (TransactionSelfie_UID == Guid.Empty)
            {
                selfieEntity = new TransactionSelfie
                {
                    CreatedOn = DateTime.UtcNow,
                    TransactionSelfie_UID = Guid.NewGuid(),
                    UserID = user.UserID
                };
                TransactionSelfie_UID = selfieEntity.TransactionSelfie_UID.Value;
            }
            else
            {
                selfieEntity = _notaryoDBContext.TransactionSelfies.FirstOrDefault(e => e.TransactionSelfie_UID == TransactionSelfie_UID);
            }
            selfieEntity.File = Convert.FromBase64String(SelfieBase64Image.Split(",")[1]);

            if (selfieEntity.TransactionID > 0)
            {
                _notaryoDBContext.TransactionSelfies.Update(selfieEntity);
            }
            else
            {
                _notaryoDBContext.TransactionSelfies.Add(selfieEntity);
            }
            _notaryoDBContext.SaveChanges();

            var identificationDocuments = _notaryoDBContext.IdentificationDocuments.Where(e => e.UserID == user.UserID);
            var identificationDocument = identificationDocuments.First();

            var selfiePath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "Selfies");
            if (!System.IO.Directory.Exists(selfiePath))
            {
                System.IO.Directory.CreateDirectory(selfiePath);
            }
            var identificationDocumentPath = System.IO.Path.Combine(selfiePath, $"{identificationDocument.IdentificationDocument_UID}.jpg");
            var selfieImagePath = System.IO.Path.Combine(selfiePath, $"{TransactionSelfie_UID}.png");

            var apiKey = _configuration.GetValue<string>("CompreFaceConfig:APIKey");
            var client = _compreFaceClient.GetCompreFaceService<VerificationService>(apiKey);
            var faceVerificationRequest = new FaceVerificationRequestByBytes()
            {
                SourceImageInBytes = selfieEntity.File,
                TargetImageInBytes = identificationDocument.File,
                DetProbThreshold = 0.81m,
                Limit = 1,
                Status = false,
                FacePlugins = []
            };
            try
            {
                var result = await client.VerifyAsync(faceVerificationRequest);
                var faceMatches = result.Result.SelectMany(x => x.FaceMatches);

                if (faceMatches.Any())
                {
                    var newTransaction = new Transaction
                    {
                        TransactionDate = DateTime.UtcNow,
                        CreatedOn = DateTime.UtcNow,
                        PrincipalID = user.UserID,
                        Status = nameof(TransactionStatus.New),
                        Transaction_UID = Guid.NewGuid()
                    };
                    _notaryoDBContext.Transactions.Add(newTransaction);
                    selfieEntity.Transaction = newTransaction;
                    _notaryoDBContext.SaveChanges();

                    return RedirectToPage($"/Principal/NotaryoSteps/UploadDocument/{newTransaction.Transaction_UID}");
                }
                ModelState.AddModelError("", "Face Verification Failed");
            }
            catch (Exception ex)
            {
                // capture error here
                ModelState.AddModelError("", ex.Message);
            }
            return Page();
        }

        //private string GetSelfieUrl()
        //{
        //    var qb = new QueryBuilder
        //    {
        //        { "handler", "ViewImage" },
        //        { "TransactionSelfie_UID", TransactionSelfie_UID.ToString() }
        //    };
        //    var url = $"{Request.Scheme}://{Request.Host}/Principal/NotaryoSteps/TakeSelfie" + qb;
        //    return url;
        //}

        //private string GetIdentificationDocumentUrl(Guid document_UID)
        //{
        //    var qb = new QueryBuilder
        //    {
        //        { "handler", "ViewImage" },
        //        { "IdentificationDocument_UID", document_UID.ToString() }
        //    };
        //    var url = $"{Request.Scheme}://{Request.Host}/Principal/IdentificationDocument/IdentificationDocument" + qb;
        //    return url;
        //}

        [AllowAnonymous]
        public IActionResult OnGetViewImage()
        {
            if (TransactionSelfie_UID == Guid.Empty)
            {
                return NotFound();
            }

            var selfie = _notaryoDBContext.TransactionSelfies.FirstOrDefault(e => e.TransactionSelfie_UID == TransactionSelfie_UID);
            if (selfie == null)
            {
                return NotFound();
            }

            return File(selfie.File, "image/png");
        }

        [BindProperty, Required]
        public string SelfieBase64Image { get; set; }

        [BindProperty(SupportsGet = true)]
        public Guid TransactionSelfie_UID { get; set; }
    }
}