using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.ValueGeneration;
using Modules.User.Database.Database.Entities;

namespace Modules.User.Database.Database;

public class UserDbContext : DbContext
{
    public DbSet<Account> Accounts { get; set; }
    public DbSet<Entities.User> Users { get; set; }
    public DbSet<Session> Sessions { get; set; }

    public UserDbContext(DbContextOptions<UserDbContext> options) : base(options)
    {

    }

    protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
    {
        configurationBuilder.Properties<Enum>().HaveConversion<string>();
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Entities.User>(q =>
        {
            q.HasOne(q => q.Account).WithOne(q => q.User).HasForeignKey<Account>(q => q.UserId);
            q.OwnsOne(q => q.RegionalSettings);
            q.Property(q => q.NickName).HasMaxLength(32);
            q.Property(q => q.FirstName).HasMaxLength(32);
            q.Property(q => q.LastName).HasMaxLength(128);
            q.Property(q => q.Patronymic).HasMaxLength(64);
        });

        modelBuilder.Entity<Account>(q =>
        {
            q.Property(q => q.Email).HasMaxLength(128);
            q.HasMany(q => q.Sessions).WithOne().HasForeignKey(q => q.AccountId);
            q.Property(q => q.CreationDate).HasDefaultValueSql("now()").ValueGeneratedOnAdd().HasValueGenerator(typeof(DatetimeNowValueGenerator));
        });

        modelBuilder.Entity<Session>(q =>
        {
            //q.Property(q => q.DeviceInfo).HasMaxLength(128);
            //q.Property(q => q.UserAgent).HasMaxLength(128);
            q.OwnsOne(q => q.ClientInfo, q =>
            {
                q.Property(q => q.UserAgent).HasMaxLength(256);
                q.Property(q => q.Country).HasMaxLength(96);
                q.Property(q => q.Region).HasMaxLength(128);
            });
            q.Property(q => q.RefreshToken).HasMaxLength(172); //128 bytes to base64
            q.Property(q => q.ExpiredDate).HasDefaultValueSql("'0001-01-01 00:00:00+00'").ValueGeneratedOnAdd();
            q.Property(q => q.LastUpdate).HasDefaultValueSql("now()").ValueGeneratedOnAddOrUpdate();
            //q.Property(q => q.LastUpdate).HasDefaultValueSql("now()").ValueGeneratedOnAddOrUpdate().HasValueGenerator(typeof(DatetimeNowValueGenerator));
        });
    }

    private class DatetimeNowValueGenerator : ValueGenerator<DateTime>
    {
        public override bool GeneratesTemporaryValues => false;

        public override DateTime Next(EntityEntry entry)
        {
            return DateTime.UtcNow;
        }
    }
}