using System.Linq.Expressions;
using Bogus;
using Microsoft.EntityFrameworkCore;
using Silk_Road_Api.DatabaseContext;
using Silk_Road_Api.Models;

namespace Silk_Road_Api.Repositories;

public class DrugRepository : Repository, IDrugRepository
{
    private static readonly List<string> prefixes = ["Neuro", "Bio", "Cyber", "Synth", "Nano", "Micro", "Hyper", "Psycho"];
    private static readonly List<string> roots = ["zym", "plex", "morp", "cyto", "gen", "nerv", "neuro", "bio", "pharm", "morph"];
    private static readonly List<string> suffixes = ["x", "z", "on", "ex", "ol", "ine", "ium", "ane", "ide", "os"];
    public DrugRepository(SilkRoadApiContext context) : base(context)
    {
        //GenerateDrugs(10);
    }

    public IQueryable<Drug> GetDrugs()
    {
        return AsQueryable<Drug>();
    }

    public async Task<Drug> GetDrug(int id)
    {
        return await GetAsync<Drug>(id);
    }

    public async Task<int> ExecuteCount(IQueryable<Drug> query)
    {
        Expression<Func<IQueryable<Drug>>> expression = () => query;
        return await _context.FromExpression(expression)
            .AsNoTracking()
            .Select(x => 1)
            .CountAsync()
            .ConfigureAwait(false);
    }

    public void GenerateDrugs(int n)
    {
        var drugs = new Faker<Drug>()
            .RuleFor(d => d.name, f => f.PickRandom(prefixes) + f.PickRandom(roots) + f.PickRandom(suffixes))
            .RuleFor(d => d.price, f => f.Random.Number(5, 100))
            .RuleFor(d => d.stock, f => f.Random.Number(1, 100))
            .RuleFor(d => d.manufacturerId, f => f.Random.Number(1, 10))
            .RuleFor(d => d.description, f => f.Lorem.Letter(30))
            .RuleFor(d => d.sideEffects, f => f.Lorem.Letter(30))
            .RuleFor(d => d.interactions, f => f.Lorem.Letter(30))
            .RuleFor(d => d.dosage, f => f.Lorem.Letter(30))
            .RuleFor(d => d.contraindications, f => f.Lorem.Letter(30))
            .RuleFor(d => d.warnings, f => f.Lorem.Letter(30))
            .RuleFor(d => d.storage, f => f.Lorem.Letter(30))
            .RuleFor(d => d.pregnancy, f => f.Lorem.Letter(30))
            .RuleFor(d => d.breastfeeding, f => f.Lorem.Letter(30))
            .RuleFor(d => d.overdose, f => f.Lorem.Letter(30))
            .Generate(n);
        _context.AddRange(drugs);
        _context.SaveChanges();
    }

    public async Task<IQueryable<ChartModel>> GetChartData()
    {
        var chartData = GetDrugs().GroupBy(d => d.manufacturerId)
            .Select(g => new ChartModel
            {
                ManufacturerId = g.Key,
                Count = g.Count()
            });
        return chartData;
    }
}
