using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Silk_Road_Api.Extensions;
using Silk_Road_Api.Models;
using Silk_Road_Api.Repositories;
using Silk_Road_Api.Utils;
using Silk_Road_Api.ViewModels;

namespace Silk_Road_Api.Services;

public class ManufacturerService : IManufacturerService
{
    private readonly IManufacturerRepository _manufacturerRepository;
    private readonly IDrugRepository _drugRepository;
    private readonly IMapper _mapper;

    public ManufacturerService(IDrugRepository drugRepository, IManufacturerRepository manufacturerRepository, IMapper mapper)
    {
        _drugRepository = drugRepository;
        _manufacturerRepository = manufacturerRepository;
        _mapper = mapper;
    }
    public async Task<bool> AddManufacturer(ControllerBase controller, ManufacturerViewModel manufacturerViewModel)
    {
        var user = controller.HttpContext.Session.Get<User>("user");
        if (user == null || user.id != Constants.Admin)
        {
            throw new Exception("Unauthorized");
        }
        try
        {
            var manufacturer = _mapper.Map<Manufacturer>(manufacturerViewModel);
            await _manufacturerRepository.AddAsync(manufacturer);
            return await _manufacturerRepository.SaveChangesAsync();
        }
        catch (Exception)
        {
            return false;
        }
    }

    public async Task<bool> DeleteManufacturer(ControllerBase controller, int id)
    {
        var user = controller.HttpContext.Session.Get<User>("user");
        if (user == null || user.id != Constants.Admin)
        {
            throw new Exception("Unauthorized");
        }
        try
        {
            var manufacturer = await _manufacturerRepository.GetManufacturer(id);
            _manufacturerRepository.Delete(manufacturer);
            return await _manufacturerRepository.SaveChangesAsync();
        }
        catch (Exception)
        {
            return false;
        }
    }

    public void GenerateManufacturer()
    {
        _manufacturerRepository.GenerateManufacturers();
    }

    public async Task<ManufacturerViewModel> GetManufacturer(ControllerBase controller, int id)
    {
        var user = controller.HttpContext.Session.Get<User>("user");
        if (user == null || user.id != Constants.Admin)
        {
            throw new Exception("Unauthorized");
        }
        var manufacturer = await _manufacturerRepository.GetManufacturer(id);
        if (manufacturer == null)
            throw new Exception("Manufacturer not found");
        var viewModel = _mapper.Map<ManufacturerViewModel>(manufacturer);
        viewModel.totalCount = _drugRepository.GetDrugs().Where(d => d.manufacturerId == id)?.Count() ?? 0;
        return viewModel;
    }

    public async Task<SearchOutput<ManufacturerViewModel>> GetManufacturers(ControllerBase controller, SearchInput input)
    {
        var user = controller.HttpContext.Session.Get<User>("user");
        if (user == null || user.id != Constants.Admin)
        {
            throw new Exception("Unauthorized");
        }
        var output = new SearchOutput<ManufacturerViewModel>
        {
            Page = input.Page,
            PageSize = input.PageSize
        };
        var drugs = _drugRepository.GetDrugs();
        var viewModel = _manufacturerRepository.GetManufacturers().GroupJoin(drugs, m => m.id, d => d.manufacturerId, (m, d) => new
        {
            manufacturer = m,
            drugs = d.Count()

        }).Select(
            x => new ManufacturerViewModel
            {
                id = x.manufacturer.id,
                name = x.manufacturer.name,
                address = x.manufacturer.address,
                contact = x.manufacturer.contact,
                totalCount = x.drugs
            }
        );
        output.Total = viewModel.Count();
        viewModel = viewModel.Skip(input.PageSize * (input.Page - 1)).Take(input.PageSize);
        output.Items = viewModel.ToList();
        return output;
    }

    public async Task<bool> UpdateManufacturer(ControllerBase controller, ManufacturerViewModel manufacturerViewModel)
    {
        var user = controller.HttpContext.Session.Get<User>("user");
        if (user == null || user.id != Constants.Admin)
        {
            throw new Exception("Unauthorized");
        }
        try
        {
            var manufacturer = _mapper.Map<Manufacturer>(manufacturerViewModel);
            _manufacturerRepository.Update(manufacturer);
            return await _manufacturerRepository.SaveChangesAsync();
        }
        catch (Exception)
        {
            return false;
        }
    }
}
