using BukiVedi.Shared.Entities;
using BukiVedi.Shared.Services.MongoDB;
using MongoDB.Driver;
using ZeroLevel;

namespace BukiVedi.Shared.Services
{
    public static class Tables
    {
        #region Mongo
        static MongoClient _client;
        static string DBName = "BukiVedi";

        public static IRepository<Book> _books;
        public static IRepository<Author> _authors;
        public static IRepository<Genre> _genres;
        public static IRepository<DBCacheRecord> _cache;
        public static IRepository<Member> _members;
        private static IRepository<BookNote> _bookNotesRepository;
        private static IRepository<DisgustingAuthor> _disgustingAuthorsRepository;
        private static IRepository<DisgustingBook> _disgustingBooksRepository;
        private static IRepository<FavoriteAuthor> _favoriteAuthorsRepository;
        private static IRepository<FavoriteBook> _favoriteBooksRepository;
        private static IRepository<ReadQueueItem> _readQueueReporitory;
        private static IRepository<UserTag> _userTagRepository;
        #endregion

        static Tables()
        {
            var settings = AppSettings.Settings;
            _client = MongoDbConnectionProvider.CreateClient(settings.MongoDB.ConnectionString, settings.MongoDB.WaitQueueLimit, settings.MongoDB.MaxConnectionPoolSize);
            _books = new MongoRepository<Book>(_client, DBName, "books");
            _authors = new MongoRepository<Author>(_client, DBName, "authors");
            _genres = new MongoRepository<Genre>(_client, DBName, "genres");
            _cache = new MongoRepository<DBCacheRecord>(_client, DBName, "cache");
            _members = new MongoRepository<Member>(_client, DBName, "Accounts");

            _bookNotesRepository = new MongoRepository<BookNote>(_client, DBName, "bookNotes");
            _disgustingAuthorsRepository = new MongoRepository<DisgustingAuthor>(_client, DBName, "disgustingAuthors");
            _disgustingBooksRepository = new MongoRepository<DisgustingBook>(_client, DBName, "disgustingBooks");
            _favoriteAuthorsRepository = new MongoRepository<FavoriteAuthor>(_client, DBName, "favoriteAuthors");
            _favoriteBooksRepository = new MongoRepository<FavoriteBook>(_client, DBName, "favoriteBooks");
            _readQueueReporitory = new MongoRepository<ReadQueueItem>(_client, DBName, "readQueue");
            _userTagRepository = new MongoRepository<UserTag>(_client, DBName, "userTags");

            CreateCacheIndex();
            CreateBookIndex();
            CreateAuthorIndex();
            CreateTagIndex();
        }
        public static IRepository<Book> Books => _books;
        public static IRepository<Author> Authors => _authors;
        public static IRepository<Genre> Genres => _genres;
        public static IRepository<DBCacheRecord> Cache => _cache;
        public static IRepository<Member> Members => _members;

        public static IRepository<BookNote> BookNotes => _bookNotesRepository;
        public static IRepository<DisgustingAuthor> DisgustingAuthors => _disgustingAuthorsRepository;
        public static IRepository<DisgustingBook> DisgustingBooks => _disgustingBooksRepository;
        public static IRepository<FavoriteAuthor> FavoriteAuthors => _favoriteAuthorsRepository;
        public static IRepository<FavoriteBook> FavoriteBooks => _favoriteBooksRepository;
        public static IRepository<ReadQueueItem> ReadQueue => _readQueueReporitory;
        public static IRepository<UserTag> UserTag => _userTagRepository;

        private static void CreateCacheIndex()
        {
            var entityIndexOption = new CreateIndexOptions { Name = "idx_cache_key", };
            var entityIndexModel = new CreateIndexModel<DBCacheRecord>(Builders<DBCacheRecord>.IndexKeys.Ascending(f => f.Key), entityIndexOption);
            Cache.Collection.Indexes.CreateOne(entityIndexModel);
            Log.Info($"[Tables.CreateCacheIndex] DBCacheRecord.Key index created");
        }

        private static void CreateBookIndex()
        {
            {
                var options = new CreateIndexOptions { DefaultLanguage = "russian", Name = "idx_book_title" };
                var indexModel = new CreateIndexModel<Book>(Builders<Book>.IndexKeys.Text(x => x.Title), options);
                Books.Collection.Indexes.CreateOne(indexModel);
                Log.Info($"[Tables.CreateBookIndex] Book Title FTS index created");
            }
            {
                var entityIndexOption = new CreateIndexOptions { Name = "idx_book_author", };
                var entityIndexModel = new CreateIndexModel<Book>(Builders<Book>.IndexKeys.Ascending(f => f.AuthorIds), entityIndexOption);
                Books.Collection.Indexes.CreateOne(entityIndexModel);
                Log.Info($"[Tables.CreateBookIndex] Book AuthorId index created");
            }
            {
                var entityIndexOption = new CreateIndexOptions { Name = "idx_book_genre", };
                var entityIndexModel = new CreateIndexModel<Book>(Builders<Book>.IndexKeys.Ascending(f => f.GenreId), entityIndexOption);
                Books.Collection.Indexes.CreateOne(entityIndexModel);
                Log.Info($"[Tables.CreateBookIndex] Book GenreId index created");
            }
            {
                var entityIndexOption = new CreateIndexOptions { Name = "idx_book_path", };
                var entityIndexModel = new CreateIndexModel<Book>(Builders<Book>.IndexKeys.Ascending(f => f.ArchivePath), entityIndexOption);
                Books.Collection.Indexes.CreateOne(entityIndexModel);
                Log.Info($"[Tables.CreateBookIndex] Books.ArchivePath index created");
            }
        }

        private static void CreateAuthorIndex()
        {
            var options = new CreateIndexOptions { DefaultLanguage = "russian", Name = "idx_author_name" };
            var indexModel = new CreateIndexModel<Author>(Builders<Author>.IndexKeys.Text(x => x.Name), options);
            Authors.Collection.Indexes.CreateOne(indexModel);
            Log.Info($"[Tables.CreateAuthorIndex] Author name FTS index created");
        }

        private static void CreateTagIndex()
        {
            {
                var entityIndexOption = new CreateIndexOptions { Name = "idx_tag_user", };
                var entityIndexModel = new CreateIndexModel<UserTag>(Builders<UserTag>.IndexKeys.Ascending(f => f.UserId), entityIndexOption);
                UserTag.Collection.Indexes.CreateOne(entityIndexModel);
                Log.Info($"[Tables.CreateBookIndex] UserTag.UserId index created");
            }
        }
    }
}
