using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage;
using System.Reflection;
using System.Text.Json;
using System.Text.RegularExpressions;

namespace SummerBestWebForm2.AppState;

public partial class CascadingAppState : ComponentBase, IAppState
{
  private readonly string StorageKey = "SummerBestEnrollment-KeyMotive";
  [Parameter]
  public RenderFragment? ChildContent { get; set; }
  [Inject]
  ProtectedLocalStorage? localStorage { get; set; } = default!;
  //[Inject]
  //IHttpContextAccessor? httpContextAccessor { get; set; } = default!;
  [CascadingParameter] HttpContext? httpContext { get; set; } = default!;

  bool isLoaded = false;

  public Guid SessionId { get; set; } = Guid.Empty;

  public bool isInit { get; set; } = false;

  //public CascadingAppState()
  //{
  //  Load();
  //}

  private string? _myIpAddress = string.Empty;
  public string? myIpAddress
  {
    get => _myIpAddress;
    set
    {
      _myIpAddress = value;
      Save();
    }
  }

  private DateTimeOffset _DateCreated = DateTimeOffset.Now;
  public DateTimeOffset DateCreated
  {
    get => _DateCreated;
    set
    {
      _DateCreated = value;
      Save();
    }
  }
  private DateTimeOffset _DateExpires = DateTimeOffset.Now;
  public DateTimeOffset DateExpires
  {
    get => _DateExpires;
    set
    {
      _DateExpires = value;
      Save();
    }
  }

  // (o) (O) / (o) (O) / (o) (O) / (o) (O) / (o) (O) / (o) (O) / (o) (O) / (o) (O) / (o) (O) / (o) (O) / (o) (O) / (o) (O) / (o) (O) / (o) (O) / (o) (O) / (o) (O) / (o) (O) / (o) (O) / (o) (O) / (o) (O) / (o) (O)

  protected override async Task OnAfterRenderAsync(bool firstRender)
  {
    await base.OnAfterRenderAsync(firstRender);
    if (firstRender)
    {
      await LoadAsync();
      StateHasChanged();
    }
  }

  private void Save()
  {
    new Task(async () =>
    {
      await SaveAsync();
    }).Start();
  } //Save

  public async Task SaveAsync()
  {
    if (!isLoaded) return;

    // serialize 
    var state = (IAppState)this;
    var json = JsonSerializer.Serialize(state);
    // save
    await localStorage.SetAsync(StorageKey, json);
  } //SaveAsync

  private void Load()
  {
    new Task(async () =>
    {
      await LoadAsync();
    }).Start();
  } //Load

  public async Task LoadAsync()
  {
    string remoteIpAddr = string.Empty;
    try
    {
      //remoteIpAddr = httpContextAccessor.HttpContext?.Connection.RemoteIpAddress?.ToString() ?? string.Empty;
      remoteIpAddr = this.httpContext?.Connection.RemoteIpAddress?.ToString() ?? "Not Set";
      var data = await localStorage.GetAsync<string>(StorageKey);
      var state = JsonSerializer.Deserialize<MdlAppState>(data.Value);

      if (state != null)
      {
        if (DateTimeOffset.Now < state.DateExpires)
        {
          // decide whether to set properties manually or with reflection

          // comment to set properties manually
          //this.Message = state.Message;
          //this.Count = state.Count;

          // set properties using Reflaction
          var t = typeof(IAppState);
          //var props = t.GetProperties();
          PropertyInfo[] props = t.GetProperties();
          foreach (var prop in props)
          {
            //if (!Regex.IsMatch(prop.Name, "isInit|SessionId|"))
            {
              var value = prop.GetValue(state, null);
              prop.SetValue(this, value, null);
            }
          }
        }
      }
    }
    catch (Exception ex)
    {
      // do something
    }
    isLoaded = true;
    DateExpires = DateTimeOffset.Now.AddHours(36);
    myIpAddress = remoteIpAddr;
    if (!isInit)
    {
      DateCreated = DateTimeOffset.Now;
      SessionId = Guid.NewGuid();
      isInit = true;
      await SaveAsync();
    }
    await InvokeAsync(() =>
    {
      StateHasChanged();
    });
  } //LoadAsync
}
