using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Microsoft.Extensions.Localization;
using Props.Models;
using Props.Models.Search;
using Props.Models.User;
using Props.Shop.Framework;

namespace Props.Data
{
    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public DbSet<QueryWordInfo> QueryWords { get; set; }

        public DbSet<ProductListingInfo> ProductListingInfos { get; set; }

        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<ResultsPreferences>()
            .Property(e => e.Order)
            .HasConversion(
                v => JsonSerializer.Serialize(v, (JsonSerializerOptions)null),
                v => JsonSerializer.Deserialize<List<ResultsPreferences.Category>>(v, (JsonSerializerOptions)null),
                new ValueComparer<IList<ResultsPreferences.Category>>(
                    (a, b) => a.SequenceEqual(b),
                    c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())),
                    c => (IList<ResultsPreferences.Category>)c.ToList()
                )
            );

            modelBuilder.Entity<SearchOutline>()
            .Property(e => e.DisabledShops)
            .HasConversion(
                v => JsonSerializer.Serialize(v, (JsonSerializerOptions)null),
                v => JsonSerializer.Deserialize<SearchOutline.ShopSelector>(v, (JsonSerializerOptions)null),
                new ValueComparer<SearchOutline.ShopSelector>(
                    (a, b) => a.Equals(b),
                    c => c.GetHashCode(),
                    c => new SearchOutline.ShopSelector(c)
                )
            );

            modelBuilder.Entity<SearchOutline>()
            .Property(e => e.Filters)
            .HasConversion(
                v => JsonSerializer.Serialize(v, (JsonSerializerOptions)null),
                v => JsonSerializer.Deserialize<Filters>(v, (JsonSerializerOptions)null),
                new ValueComparer<Filters>(
                    (a, b) => a.Equals(b),
                    c => c.GetHashCode(),
                    c => c.Copy()
                )
            );

            modelBuilder.Entity<ProductListingInfo>()
            .Property(e => e.ProductListing)
            .HasConversion(
                v => JsonSerializer.Serialize(v, (JsonSerializerOptions)null),
                v => JsonSerializer.Deserialize<ProductListing>(v, (JsonSerializerOptions)null),
                new ValueComparer<ProductListing>(
                    (a, b) => a.Equals(b),
                    c => c.GetHashCode(),
                    c => c.Copy()
                )
            );
        }
    }
}