using System.Text;
using System.Text.Json;
using Azure.Communication.CallAutomation;
using Azure.Storage.Queues;
using Coravel.Invocable;
using EnotaryoPH.Data;
using EnotaryoPH.Data.Entities;
using EnotaryoPH.Web.Common.Jobs.Models;

namespace EnotaryoPH.Web.Common.Jobs
{
    public class CheckRecordingAvailabilityInvocable : IInvocable
    {
        private readonly QueueClient _queueClient;
        private readonly CallAutomationClient _callAutomationClient;
        private readonly IConfiguration _configuration;
        private readonly IServiceScopeFactory _serviceScopeFactory;

        public CheckRecordingAvailabilityInvocable(QueueClient queueClient, CallAutomationClient callAutomationClient, IConfiguration configuration, IServiceScopeFactory serviceScopeFactory)
        {
            _queueClient = queueClient;
            _callAutomationClient = callAutomationClient;
            _configuration = configuration;
            _serviceScopeFactory = serviceScopeFactory;
        }

        public async Task Invoke()
        {
            var message = await _queueClient.ReceiveMessageAsync();
            if (message?.Value == null)
            {
                return;
            }
            var base64EncodedData = message.Value.Body.ToString();
            var base64EncodedBytes = Convert.FromBase64String(base64EncodedData);
            var options = new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true
            };
            var json = Encoding.UTF8.GetString(base64EncodedBytes);
            var model = JsonSerializer.Deserialize<RecordingFileStatusUpdatedModel>(json, options);
            if (model?.Data?.RecordingStorageInfo?.RecordingChunks?.Count > 0)
            {
                var dbContext = _serviceScopeFactory.CreateScope().ServiceProvider.GetRequiredService<NotaryoDBContext>();
                model.Data.RecordingStorageInfo.RecordingChunks.ForEach(async chunk =>
                {
                    var path = _configuration.GetValue<string>("VideoRecordingsLocation");
                    if (!Path.Exists(path))
                    {
                        Directory.CreateDirectory(path);
                    }
                    var fileName = Path.Combine(path, $"{chunk.DocumentId}-{chunk.Index}.mp4");
                    if (File.Exists(fileName))
                    {
                        File.Move(fileName, fileName.Replace(".mp4", $"_{DateTime.UtcNow.ToString("yyyy-MM-dd-HH-mm-dd")}.mp4"));
                    }

                    using var memoryStream = new MemoryStream();
                    await _callAutomationClient
                        .GetCallRecording().DownloadToAsync(new Uri(chunk.ContentLocation), fileName);

                    var schedule = dbContext.LawyerVideoConferenceSchedules.FirstOrDefault(sched => sched.RecordingID == model.Data.RecordingId);
                    if (schedule != null)
                    {
                        if (schedule.VideoRecording == null)
                        {
                            schedule.VideoRecording = new VideoRecording
                            {
                                CreatedOn = DateTime.UtcNow,
                                LocationType = nameof(VideoRecordingLocationType.LocalFolder),
                                VideoConferenceScheduleID = schedule.LawyerVideoConferenceScheduleID,
                                VideoRecording_UID = Guid.CreateVersion7(DateTime.UtcNow)
                            };
                        }
                        schedule.VideoRecording.Path = fileName;
                        schedule.VideoRecording.Metadata = JsonSerializer.Serialize(json);
                        dbContext.UpdateOrCreate(schedule);
                        dbContext.SaveChanges();
                    }
                });
            }
            await _queueClient.DeleteMessageAsync(message.Value.MessageId, message.Value.PopReceipt);
        }
    }
}