/// News Providers
///
/// State management for news articles using Riverpod.
/// Provides access to news data and filtering capabilities.
library;

import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:worker/core/network/dio_client.dart';
import 'package:worker/core/services/frappe_auth_provider.dart';
import 'package:worker/features/news/data/datasources/news_local_datasource.dart';
import 'package:worker/features/news/data/datasources/news_remote_datasource.dart';
import 'package:worker/features/news/domain/entities/blog_category.dart';
import 'package:worker/features/news/domain/entities/news_article.dart';
import 'package:worker/features/news/domain/repositories/news_repository.dart';
import 'package:worker/features/news/data/repositories/news_repository_impl.dart';

part 'news_provider.g.dart';

/// News Local DataSource Provider
///
/// Provides instance of NewsLocalDataSource.
@riverpod
NewsLocalDataSource newsLocalDataSource(Ref ref) {
  return NewsLocalDataSource();
}

/// News Remote DataSource Provider
///
/// Provides instance of NewsRemoteDataSource with Frappe auth service.
@riverpod
Future<NewsRemoteDataSource> newsRemoteDataSource(Ref ref) async {
  final dioClient = await ref.watch(dioClientProvider.future);
  final frappeAuthService = ref.watch(frappeAuthServiceProvider);
  return NewsRemoteDataSource(dioClient, frappeAuthService);
}

/// News Repository Provider
///
/// Provides instance of NewsRepository implementation.
@riverpod
Future<NewsRepository> newsRepository(Ref ref) async {
  final localDataSource = ref.watch(newsLocalDataSourceProvider);
  final remoteDataSource = await ref.watch(newsRemoteDataSourceProvider.future);
  return NewsRepositoryImpl(
    localDataSource: localDataSource,
    remoteDataSource: remoteDataSource,
  );
}

/// All News Articles Provider (Internal)
///
/// Fetches ALL blog posts from Frappe API sorted by published date (latest first).
/// This is the complete list used by both featured and latest articles providers.
/// Do not use this provider directly in UI - use featuredArticle or newsArticles instead.
@riverpod
Future<List<NewsArticle>> _allNewsArticles(Ref ref) async {
  final remoteDataSource = await ref.watch(newsRemoteDataSourceProvider.future);

  // Fetch blog posts from Frappe API
  final blogPosts = await remoteDataSource.getBlogPosts();

  // Convert to NewsArticle entities
  final articles = blogPosts.map((post) => post.toEntity()).toList();

  // Already sorted by published_on desc from API
  return articles;
}

/// Featured Article Provider
///
/// Returns the first article from the complete list.
/// This is the latest published article that will be displayed prominently at the top.
@riverpod
Future<NewsArticle?> featuredArticle(Ref ref) async {
  final allArticles = await ref.watch(_allNewsArticlesProvider.future);

  // Return first article if available (latest post)
  return allArticles.isNotEmpty ? allArticles.first : null;
}

/// News Articles Provider
///
/// Returns latest news articles EXCLUDING the first item (which is shown as featured).
/// This ensures each article only appears once on the page.
/// Returns AsyncValue<List<NewsArticle>> for proper loading/error handling.
@riverpod
Future<List<NewsArticle>> newsArticles(Ref ref) async {
  final allArticles = await ref.watch(_allNewsArticlesProvider.future);

  // Return all articles except first (which is featured)
  // If only 0-1 articles, return empty list
  return allArticles.length > 1 ? allArticles.sublist(1) : [];
}

/// Selected News Category Provider (Legacy - using enum)
///
/// Manages the currently selected category filter.
/// null means "All" is selected (show all categories).
@riverpod
class SelectedNewsCategory extends _$SelectedNewsCategory {
  @override
  NewsCategory? build() {
    // Default: show all categories
    return null;
  }

  /// Set selected category
  void setCategory(NewsCategory? category) {
    state = category;
  }

  /// Clear selection (show all)
  void clearSelection() {
    state = null;
  }
}

/// Selected Category Name Provider
///
/// Manages the currently selected blog category name (from Frappe API).
/// null means "All" is selected (show all categories).
///
/// Examples: "tin-tức", "dự-án", "chuyên-môn", "khuyến-mãi"
@riverpod
class SelectedCategoryName extends _$SelectedCategoryName {
  @override
  String? build() {
    // Default: show all categories
    return null;
  }

  /// Set selected category by name
  void setCategoryName(String? categoryName) {
    state = categoryName;
  }

  /// Clear selection (show all)
  void clearSelection() {
    state = null;
  }
}

/// Filtered News Articles Provider
///
/// Returns news articles filtered by selected blog category name.
/// Excludes the first article (which is shown as featured).
/// If no category is selected, returns all articles except first.
///
/// The blog_category name from API is stored in article.tags[0] for filtering.
@riverpod
Future<List<NewsArticle>> filteredNewsArticles(Ref ref) async {
  final selectedCategoryName = ref.watch(selectedCategoryNameProvider);
  final allArticles = await ref.watch(_allNewsArticlesProvider.future);

  // Get articles excluding first (which is featured)
  final articlesWithoutFeatured = allArticles.length > 1 ? allArticles.sublist(1) : <NewsArticle>[];

  // If no category selected, return all articles except first
  if (selectedCategoryName == null) {
    return articlesWithoutFeatured;
  }

  // Filter articles by blog_category name (stored in tags[0])
  return articlesWithoutFeatured.where((article) {
    // Check if article has tags and first tag matches selected category
    return article.tags.isNotEmpty && article.tags[0] == selectedCategoryName;
  }).toList();
}

/// News Article by ID Provider
///
/// Fetches a specific article by ID from the Frappe API.
/// Uses frappe.client.get endpoint to fetch the full blog post detail.
/// Used for article detail page.
@riverpod
Future<NewsArticle?> newsArticleById(Ref ref, String articleId) async {
  final repository = await ref.watch(newsRepositoryProvider.future);
  return repository.getArticleByIdFromApi(articleId);
}

/// Blog Categories Provider
///
/// Fetches all published blog categories from Frappe API.
/// Returns AsyncValue<List<BlogCategory>> (domain entities) for proper loading/error handling.
///
/// Example categories:
/// - Tin tức (News)
/// - Chuyên môn (Professional)
/// - Dự án (Projects)
/// - Khuyến mãi (Promotions)
@riverpod
Future<List<BlogCategory>> blogCategories(Ref ref) async {
  final repository = await ref.watch(newsRepositoryProvider.future);
  return repository.getBlogCategories();
}
