/// News Remote DataSource
///
/// Handles fetching news/blog data from the Frappe API.
library;

import 'package:dio/dio.dart';
import 'package:worker/core/constants/api_constants.dart';
import 'package:worker/core/network/dio_client.dart';
import 'package:worker/core/services/frappe_auth_service.dart';
import 'package:worker/features/news/data/models/blog_category_model.dart';
import 'package:worker/features/news/data/models/blog_post_model.dart';

/// News Remote Data Source
///
/// Provides methods to fetch news and blog content from the Frappe API.
/// Uses FrappeAuthService for session management.
class NewsRemoteDataSource {
  NewsRemoteDataSource(this._dioClient, this._frappeAuthService);

  final DioClient _dioClient;
  final FrappeAuthService _frappeAuthService;

  /// Get blog categories
  ///
  /// Fetches all published blog categories from Frappe.
  /// Returns a list of [BlogCategoryModel].
  ///
  /// API endpoint: POST https://land.dbiz.com/api/method/frappe.client.get_list
  /// Request body:
  /// ```json
  /// {
  ///   "doctype": "Blog Category",
  ///   "fields": ["title","name"],
  ///   "filters": {"published":1},
  ///   "order_by": "creation desc",
  ///   "limit_page_length": 0
  /// }
  /// ```
  ///
  /// Response format:
  /// ```json
  /// {
  ///   "message": [
  ///     {"title": "Tin tức", "name": "tin-tức"},
  ///     {"title": "Chuyên môn", "name": "chuyên-môn"},
  ///     ...
  ///   ]
  /// }
  /// ```
  Future<List<BlogCategoryModel>> getBlogCategories() async {
    try {
      // Get Frappe session headers
      final headers = await _frappeAuthService.getHeaders();

      // Build full API URL
      final url = '${ApiConstants.baseUrl}${ApiConstants.frappeApiMethod}${ApiConstants.frappeGetList}';

      final response = await _dioClient.post<Map<String, dynamic>>(
        url,
        data: {
          'doctype': 'Blog Category',
          'fields': ['title', 'name'],
          'filters': {'published': 1},
          'order_by': 'creation desc',
          'limit_page_length': 0,
        },
        options: Options(headers: headers),
      );

      if (response.data == null) {
        throw Exception('Empty response from server');
      }

      // Parse the response using the wrapper model
      final categoriesResponse = BlogCategoriesResponse.fromJson(response.data!);

      return categoriesResponse.message;
    } on DioException catch (e) {
      if (e.response?.statusCode == 404) {
        throw Exception('Blog categories endpoint not found');
      } else if (e.response?.statusCode == 500) {
        throw Exception('Server error while fetching blog categories');
      } else if (e.type == DioExceptionType.connectionTimeout) {
        throw Exception('Connection timeout while fetching blog categories');
      } else if (e.type == DioExceptionType.receiveTimeout) {
        throw Exception('Response timeout while fetching blog categories');
      } else {
        throw Exception('Failed to fetch blog categories: ${e.message}');
      }
    } catch (e) {
      throw Exception('Unexpected error fetching blog categories: $e');
    }
  }

  /// Get blog posts
  ///
  /// Fetches all published blog posts from Frappe.
  /// Returns a list of [BlogPostModel].
  ///
  /// API endpoint: POST https://land.dbiz.com/api/method/frappe.client.get_list
  /// Request body:
  /// ```json
  /// {
  ///   "doctype": "Blog Post",
  ///   "fields": ["name","title","published_on","blogger","blog_intro","content","meta_image","meta_description","blog_category"],
  ///   "filters": {"published":1},
  ///   "order_by": "published_on desc",
  ///   "limit_page_length": 0
  /// }
  /// ```
  ///
  /// Response format:
  /// ```json
  /// {
  ///   "message": [
  ///     {
  ///       "name": "post-slug",
  ///       "title": "Post Title",
  ///       "published_on": "2024-01-01 10:00:00",
  ///       "blogger": "Author Name",
  ///       "blog_intro": "Short introduction...",
  ///       "content": "<p>Full HTML content...</p>",
  ///       "meta_image": "https://...",
  ///       "meta_description": "SEO description",
  ///       "blog_category": "tin-tức"
  ///     },
  ///     ...
  ///   ]
  /// }
  /// ```
  Future<List<BlogPostModel>> getBlogPosts() async {
    try {
      // Get Frappe session headers
      final headers = await _frappeAuthService.getHeaders();

      // Build full API URL
      const url =
          '${ApiConstants.baseUrl}${ApiConstants.frappeApiMethod}${ApiConstants.frappeGetList}';

      final response = await _dioClient.post<Map<String, dynamic>>(
        url,
        data: {
          'doctype': 'Blog Post',
          'fields': [
            'name',
            'title',
            'published_on',
            'blogger',
            'blog_intro',
            'meta_image',
            'meta_description',
            'blog_category',
          ],
          'filters': {'published': 1},
          'order_by': 'published_on desc',
          'limit_page_length': 0,
        },
        options: Options(headers: headers),
      );

      if (response.data == null) {
        throw Exception('Empty response from server');
      }

      // Parse the response using the wrapper model
      final postsResponse = BlogPostsResponse.fromJson(response.data!);

      return postsResponse.message;
    } on DioException catch (e) {
      if (e.response?.statusCode == 404) {
        throw Exception('Blog posts endpoint not found');
      } else if (e.response?.statusCode == 500) {
        throw Exception('Server error while fetching blog posts');
      } else if (e.type == DioExceptionType.connectionTimeout) {
        throw Exception('Connection timeout while fetching blog posts');
      } else if (e.type == DioExceptionType.receiveTimeout) {
        throw Exception('Response timeout while fetching blog posts');
      } else {
        throw Exception('Failed to fetch blog posts: ${e.message}');
      }
    } catch (e) {
      throw Exception('Unexpected error fetching blog posts: $e');
    }
  }

  /// Get blog post detail by name
  ///
  /// Fetches a single blog post by its unique name (slug) from Frappe.
  /// Returns a [BlogPostModel].
  ///
  /// API endpoint: POST https://land.dbiz.com/api/method/frappe.client.get
  /// Request body:
  /// ```json
  /// {
  ///   "doctype": "Blog Post",
  ///   "name": "post-slug"
  /// }
  /// ```
  ///
  /// Response format:
  /// ```json
  /// {
  ///   "message": {
  ///     "name": "post-slug",
  ///     "title": "Post Title",
  ///     "published_on": "2024-01-01 10:00:00",
  ///     "blogger": "Author Name",
  ///     "blog_intro": "Short introduction...",
  ///     "content": "<p>Full HTML content...</p>",
  ///     "meta_image": "https://...",
  ///     "meta_description": "SEO description",
  ///     "blog_category": "tin-tức"
  ///   }
  /// }
  /// ```
  Future<BlogPostModel> getBlogPostDetail(String postName) async {
    try {
      // Get Frappe session headers
      final headers = await _frappeAuthService.getHeaders();

      // Build full API URL for frappe.client.get
      const url =
          '${ApiConstants.baseUrl}${ApiConstants.frappeApiMethod}${ApiConstants.frappeGet}';

      final response = await _dioClient.post<Map<String, dynamic>>(
        url,
        data: {
          'doctype': 'Blog Post',
          'name': postName,
        },
        options: Options(headers: headers),
      );

      if (response.data == null) {
        throw Exception('Empty response from server');
      }

      // The response has the blog post data directly in "message" field
      final messageData = response.data!['message'];
      if (messageData == null) {
        throw Exception('Blog post not found: $postName');
      }

      // Parse the blog post from the message field
      return BlogPostModel.fromJson(messageData as Map<String, dynamic>);
    } on DioException catch (e) {
      if (e.response?.statusCode == 404) {
        throw Exception('Blog post not found: $postName');
      } else if (e.response?.statusCode == 500) {
        throw Exception('Server error while fetching blog post detail');
      } else if (e.type == DioExceptionType.connectionTimeout) {
        throw Exception('Connection timeout while fetching blog post detail');
      } else if (e.type == DioExceptionType.receiveTimeout) {
        throw Exception('Response timeout while fetching blog post detail');
      } else {
        throw Exception('Failed to fetch blog post detail: ${e.message}');
      }
    } catch (e) {
      throw Exception('Unexpected error fetching blog post detail: $e');
    }
  }
}
