using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using API.Constants;
using API.Entities;
using API.Entities.Enums;
using API.Services;
using Kavita.Common;
using Kavita.Common.EnvironmentInfo;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
namespace API.Data
{
    public static class Seed
    {
        /// 
        /// Generated on Startup. Seed.SeedSettings must run before
        /// 
        public static IList DefaultSettings;
        public static async Task SeedRoles(RoleManager roleManager)
        {
            var roles = typeof(PolicyConstants)
                .GetFields(BindingFlags.Public | BindingFlags.Static)
                .Where(f => f.FieldType == typeof(string))
                .ToDictionary(f => f.Name,
                    f => (string) f.GetValue(null)).Values
                .Select(policyName => new AppRole() {Name = policyName})
                .ToList();
            foreach (var role in roles)
            {
                var exists = await roleManager.RoleExistsAsync(role.Name);
                if (!exists)
                {
                    await roleManager.CreateAsync(role);
                }
            }
        }
        public static async Task SeedSettings(DataContext context, IDirectoryService directoryService)
        {
            await context.Database.EnsureCreatedAsync();
            DefaultSettings = new List()
            {
                new () {Key = ServerSettingKey.CacheDirectory, Value = directoryService.CacheDirectory},
                new () {Key = ServerSettingKey.TaskScan, Value = "daily"},
                new () {Key = ServerSettingKey.LoggingLevel, Value = "Information"}, // Not used from DB, but DB is sync with appSettings.json
                new () {Key = ServerSettingKey.TaskBackup, Value = "daily"},
                new () {Key = ServerSettingKey.BackupDirectory, Value = Path.GetFullPath(DirectoryService.BackupDirectory)},
                new () {Key = ServerSettingKey.Port, Value = "5000"}, // Not used from DB, but DB is sync with appSettings.json
                new () {Key = ServerSettingKey.AllowStatCollection, Value = "true"},
                new () {Key = ServerSettingKey.EnableOpds, Value = "false"},
                new () {Key = ServerSettingKey.EnableAuthentication, Value = "true"},
                new () {Key = ServerSettingKey.BaseUrl, Value = "/"},
                new () {Key = ServerSettingKey.InstallId, Value = HashUtil.AnonymousToken()},
                new () {Key = ServerSettingKey.InstallVersion, Value = BuildInfo.Version.ToString()},
                new () {Key = ServerSettingKey.BookmarkDirectory, Value = directoryService.BookmarkDirectory},
            };
            foreach (var defaultSetting in DefaultSettings)
            {
                var existing = context.ServerSetting.FirstOrDefault(s => s.Key == defaultSetting.Key);
                if (existing == null)
                {
                    await context.ServerSetting.AddAsync(defaultSetting);
                }
            }
            await context.SaveChangesAsync();
            // Port and LoggingLevel are managed in appSettings.json. Update the DB values to match
            context.ServerSetting.First(s => s.Key == ServerSettingKey.Port).Value =
                Configuration.Port + string.Empty;
            context.ServerSetting.First(s => s.Key == ServerSettingKey.LoggingLevel).Value =
                Configuration.LogLevel + string.Empty;
            context.ServerSetting.First(s => s.Key == ServerSettingKey.CacheDirectory).Value =
                directoryService.CacheDirectory + string.Empty;
            context.ServerSetting.First(s => s.Key == ServerSettingKey.BackupDirectory).Value =
                DirectoryService.BackupDirectory + string.Empty;
            await context.SaveChangesAsync();
        }
        public static async Task SeedUserApiKeys(DataContext context)
        {
            await context.Database.EnsureCreatedAsync();
            var users = await context.AppUser.ToListAsync();
            foreach (var user in users)
            {
                if (string.IsNullOrEmpty(user.ApiKey))
                {
                    user.ApiKey = HashUtil.ApiKey();
                }
            }
            await context.SaveChangesAsync();
        }
    }
}