using DbFirst.BlazorWebApp.Models.Grid;
using DbFirst.Contracts.Layouts;
using Microsoft.JSInterop;
using System.Text.Json;

namespace DbFirst.BlazorWebApp.Services
{
    public class BandLayoutService(ILayoutApiClient layoutApi, IJSRuntime jsRuntime)
    {
        private const string LayoutUserStorageKey = "layoutUser";
        private readonly JsonSerializerOptions _jsonOptions = new(JsonSerializerDefaults.Web);
        private string? _cachedLayoutUser;

        public async Task<string> EnsureLayoutUserAsync()
        {
            if (!string.IsNullOrWhiteSpace(_cachedLayoutUser))
                return _cachedLayoutUser;

            var layoutUser = await jsRuntime.InvokeAsync<string?>("localStorage.getItem", LayoutUserStorageKey);
            if (string.IsNullOrWhiteSpace(layoutUser))
            {
                layoutUser = Guid.NewGuid().ToString("N");
                await jsRuntime.InvokeVoidAsync("localStorage.setItem", LayoutUserStorageKey, layoutUser);
            }

            _cachedLayoutUser = layoutUser;
            return _cachedLayoutUser;
        }

        public async Task<BandLayout> LoadBandLayoutAsync(
            string layoutType,
            string layoutKey,
            string layoutUser,
            Dictionary<string, ColumnDefinition> columnLookup)
        {
            if (string.IsNullOrWhiteSpace(layoutUser))
                return new BandLayout();

            var stored = await layoutApi.GetAsync(layoutType, layoutKey, layoutUser);
            if (stored != null && !string.IsNullOrWhiteSpace(stored.LayoutData))
            {
                var parsed = JsonSerializer.Deserialize<BandLayout>(stored.LayoutData, _jsonOptions);
                return NormalizeBandLayout(parsed, columnLookup);
            }

            return new BandLayout();
        }

        public async Task SaveBandLayoutAsync(
            string layoutType,
            string layoutKey,
            string layoutUser,
            BandLayout bandLayout)
        {
            var layoutData = JsonSerializer.Serialize(bandLayout, _jsonOptions);
            await layoutApi.UpsertAsync(new LayoutDto
            {
                LayoutType = layoutType,
                LayoutKey = layoutKey,
                UserName = layoutUser,
                LayoutData = layoutData
            });
        }

        public async Task ResetBandLayoutAsync(
            string layoutType,
            string layoutKey,
            string layoutUser)
        {
            await layoutApi.DeleteAsync(layoutType, layoutKey, layoutUser);
        }

        public Dictionary<string, string> BuildAssignmentsFromLayout(BandLayout layout)
        {
            var assignments = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
            foreach (var band in layout.Bands)
            {
                foreach (var column in band.Columns)
                {
                    assignments[column] = band.Id;
                }
            }
            return assignments;
        }

        public BandLayout NormalizeBandLayout(
            BandLayout? layout,
            Dictionary<string, ColumnDefinition> columnLookup)
        {
            layout ??= new BandLayout();
            layout.Bands ??= [];
            layout.ColumnOrder ??= [];
            layout.ColumnWidths ??= [];

            foreach (var band in layout.Bands)
            {
                if (string.IsNullOrWhiteSpace(band.Id))
                    band.Id = Guid.NewGuid().ToString("N");

                if (string.IsNullOrWhiteSpace(band.Caption))
                    band.Caption = "Band";

                band.Columns = band.Columns?.Where(columnLookup.ContainsKey).ToList() ?? new List<string>();
            }

            return layout;
        }
    }
}