using DomainResults.Common;
using Core.Enumerations;
using ExtensionMethods;
using DataProviders.Collections;
using WeatherForecast.Models.Requests;
using WeatherForecast.Models.Responses;
using WeatherForecast.Services.Abstractions;
namespace WeatherForecast.Services {
  /// 
  /// 
  /// 
  public interface IBlogItemService {
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    (Guid?, IDomainResult) Post(Guid siteId, BlogItemRequestModel requestModel);
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    (BlogItemResponseModel?, IDomainResult) Get(Guid siteId, Guid blogId);
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    (BlogItemResponseModel?, IDomainResult) GetSlug(Guid siteId, string slug);
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    (Guid?, IDomainResult) Update(Guid siteId, Guid blogId, BlogItemRequestModel requestData);
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    IDomainResult Delete(Guid siteId, Guid blogId);
  }
  /// 
  /// 
  /// 
  public class BlogItemService : PostItemServiceBase, IBlogItemService {
    private readonly IBlogCatalogDataProvider _blogCatalogDataProvider;
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    public BlogItemService(
      ILogger logger,
      IBlogCatalogDataProvider blogCatalogDataProvider,
      ICategoryDataProvider categoryDataProvider
    ) : base(logger, categoryDataProvider) {
      _blogCatalogDataProvider = blogCatalogDataProvider;
    }
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    public (Guid?, IDomainResult) Post(Guid siteId, BlogItemRequestModel requestData) {
      try {
        var item = requestData.ToDomainObject();
        item.SiteId = siteId;
        var (_, getResult) = _blogCatalogDataProvider.GetBySlugs(item.SiteId, item.L10n.Select(x => x.Slug).ToList());
        if (getResult.IsSuccess)
          return IDomainResult.Failed();
        // TODO: should be recovered from users by jwt
        item.Author = "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60".ToGuid();
        var (categories, addCategoriesResult) = AddCategoryIfNullOrEmpty(siteId, requestData.Categories);
        if (!addCategoriesResult.IsSuccess || categories == null)
          return (null, addCategoriesResult);
        item.Categories = categories;
        var (id, insertResult) = _blogCatalogDataProvider.Insert(item);
        if (!insertResult.IsSuccess)
          return IDomainResult.Failed();
        return IDomainResult.Success(id);
      }
      catch (Exception ex) {
        _logger.LogError(ex, "Unhandled exception");
        return IDomainResult.Failed(ex.Message);
      }
    }
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    public (BlogItemResponseModel?, IDomainResult) Get(Guid siteId, Guid blogId) {
      try {
        var (item, result) = _blogCatalogDataProvider.Get(siteId, blogId);
        if (!result.IsSuccess || item == null)
          return (null, result);
        var (categories, getCategoryResult) = _categoryDataProvider.GetMany(siteId, item.Categories);
        if (!getCategoryResult.IsSuccess || categories == null)
          return IDomainResult.Failed();
        return IDomainResult.Success(new BlogItemResponseModel(item, categories));
      }
      catch (Exception ex) {
        _logger.LogError(ex, "Unhandled exception");
        return IDomainResult.Failed(ex.Message);
      }
    }
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    public (BlogItemResponseModel?, IDomainResult) GetSlug(Guid siteId, string slug) {
      try {
        var (item, result) = _blogCatalogDataProvider.GetBySlug(siteId, slug);
        if (!result.IsSuccess || item == null)
          return (null, result);
        var locale = item.L10n.SingleOrDefault(x => x.Slug == slug)?.Locale ?? Locales.Us;
        var (categories, getCategoryResult) = _categoryDataProvider.GetMany(siteId, item.Categories);
        if (!getCategoryResult.IsSuccess || categories == null)
          return IDomainResult.Failed();
        return IDomainResult.Success(new BlogItemResponseModel(item, categories, locale));
      }
      catch (Exception ex) {
        _logger.LogError(ex, "Unhandled exception");
        return IDomainResult.Failed(ex.Message);
      }
    }
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    public (Guid?, IDomainResult) Update(Guid siteId, Guid blogId, BlogItemRequestModel requestData) {
      try {
        var (item, getResult) = _blogCatalogDataProvider.Get(siteId, blogId);
        if (!getResult.IsSuccess || item == null)
          return (null, getResult);
        // construct domain object from model
        var newItem = requestData.ToDomainObject();
        newItem.Id = item.Id;
        newItem.SiteId = siteId;
        newItem.Created = item.Created;
        newItem.Author = item.Author;
        var (categories, addCategoriesResult) = AddCategoryIfNullOrEmpty(siteId, requestData.Categories);
        if (!addCategoriesResult.IsSuccess || categories == null)
          return (null, addCategoriesResult);
        item.Categories = categories;
        if (!item.Equals(newItem)) {
          var (id, updateResult) = _blogCatalogDataProvider.Update(newItem);
          if (!updateResult.IsSuccess || id == null)
            return (null, updateResult);
        }
        return IDomainResult.Success(item.Id);
      }
      catch (Exception ex) {
        _logger.LogError(ex, "Unhandled exception");
        return IDomainResult.Failed(ex.Message);
      }
    }
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    public IDomainResult Delete(Guid siteId, Guid blogId) {
      try {
        var (item, getResult) = _blogCatalogDataProvider.Get(siteId, blogId);
        if (!getResult.IsSuccess || item == null)
          return getResult;
        var result = _blogCatalogDataProvider.Delete(item.Id);
        if (!result.IsSuccess)
          return result;
        return IDomainResult.Success();
      }
      catch (Exception ex) {
        _logger.LogError(ex, "Unhandled exception");
        return IDomainResult.Failed(ex.Message);
      }
    }
  }
}