/// Blog Post Model for Frappe API
///
/// Maps to Frappe Blog Post doctype from blog.sh API.
library;

import 'package:json_annotation/json_annotation.dart';
import 'package:worker/core/constants/api_constants.dart';
import 'package:worker/features/news/domain/entities/news_article.dart';

part 'blog_post_model.g.dart';

/// Blog Post Model
///
/// Represents a blog post from Frappe ERPNext system.
/// Fields match the API response from frappe.client.get_list for Blog Post doctype.
@JsonSerializable()
class BlogPostModel {
  /// Unique post identifier (docname)
  final String name;

  /// Post title
  final String title;

  /// Publication date (ISO 8601 string)
  @JsonKey(name: 'published_on')
  final String? publishedOn;

  /// Author/blogger name
  final String? blogger;

  /// Short introduction/excerpt
  @JsonKey(name: 'blog_intro')
  final String? blogIntro;

  /// Full HTML content (legacy field)
  final String? content;

  /// Full HTML content (new field from Frappe)
  @JsonKey(name: 'content_html')
  final String? contentHtml;

  /// Featured/meta image URL
  @JsonKey(name: 'meta_image')
  final String? metaImage;

  /// Meta description for SEO
  @JsonKey(name: 'meta_description')
  final String? metaDescription;

  /// Blog category name
  @JsonKey(name: 'blog_category')
  final String? blogCategory;

  /// Constructor
  const BlogPostModel({
    required this.name,
    required this.title,
    this.publishedOn,
    this.blogger,
    this.blogIntro,
    this.content,
    this.contentHtml,
    this.metaImage,
    this.metaDescription,
    this.blogCategory,
  });

  /// Create model from JSON
  factory BlogPostModel.fromJson(Map<String, dynamic> json) =>
      _$BlogPostModelFromJson(json);

  /// Convert model to JSON
  Map<String, dynamic> toJson() => _$BlogPostModelToJson(this);

  /// Convert to domain entity (NewsArticle)
  ///
  /// Stores the original blog_category name in tags[0] for filtering purposes.
  NewsArticle toEntity() {
    // Parse published date
    DateTime publishedDate = DateTime.now();
    if (publishedOn != null) {
      try {
        publishedDate = DateTime.parse(publishedOn!);
      } catch (e) {
        // Use current date if parsing fails
        publishedDate = DateTime.now();
      }
    }

    // Use content_html preferentially, fall back to content
    final htmlContent = contentHtml ?? content;

    // Excerpt is ONLY from blog_intro (plain text)
    final excerpt = blogIntro ?? '';

    // Use meta image with full URL path
    String imageUrl;
    if (metaImage != null && metaImage!.isNotEmpty) {
      // If meta_image starts with /, prepend the base URL
      if (metaImage!.startsWith('/')) {
        imageUrl = '${ApiConstants.baseUrl}$metaImage';
      } else if (metaImage!.startsWith('http')) {
        imageUrl = metaImage!;
      } else {
        imageUrl = '${ApiConstants.baseUrl}/$metaImage';
      }
    } else {
      imageUrl = 'https://via.placeholder.com/400x300?text=${Uri.encodeComponent(title)}';
    }

    // Parse category
    final category = _parseCategory(blogCategory ?? '');

    // Calculate reading time (rough estimate: 200 words per minute)
    final wordCount = (htmlContent ?? excerpt).split(' ').length;
    final readingTime = (wordCount / 200).ceil().clamp(1, 60);

    return NewsArticle(
      id: name,
      title: title,
      excerpt: excerpt.isNotEmpty
          ? (excerpt.length > 300 ? '${excerpt.substring(0, 300)}...' : excerpt)
          : 'Không có mô tả',
      content: htmlContent,
      imageUrl: imageUrl,
      category: category,
      publishedDate: publishedDate,
      viewCount: 0, // Not provided by API
      readingTimeMinutes: readingTime,
      isFeatured: false, // Not provided by API
      authorName: blogger,
      authorAvatar: null, // Not provided by API
      tags: blogCategory != null ? [blogCategory!] : [], // Store original category name for filtering
      likeCount: 0, // Not provided by API
      commentCount: 0, // Not provided by API
      shareCount: 0, // Not provided by API
    );
  }

  /// Parse category from blog category name
  static NewsCategory _parseCategory(String categoryName) {
    final lower = categoryName.toLowerCase();
    if (lower.contains('tin') || lower.contains('news')) {
      return NewsCategory.news;
    } else if (lower.contains('chuyên') ||
        lower.contains('kỹ thuật') ||
        lower.contains('professional') ||
        lower.contains('technique')) {
      return NewsCategory.professional;
    } else if (lower.contains('dự án') ||
        lower.contains('project') ||
        lower.contains('công trình')) {
      return NewsCategory.projects;
    } else if (lower.contains('sự kiện') || lower.contains('event')) {
      return NewsCategory.events;
    } else if (lower.contains('khuyến mãi') ||
        lower.contains('promotion') ||
        lower.contains('ưu đãi')) {
      return NewsCategory.promotions;
    }
    return NewsCategory.news;
  }

  @override
  String toString() {
    return 'BlogPostModel(name: $name, title: $title, category: $blogCategory, '
        'publishedOn: $publishedOn, hasContentHtml: ${contentHtml != null})';
  }
}

/// Response wrapper for Blog Post list API
@JsonSerializable()
class BlogPostsResponse {
  final List<BlogPostModel> message;

  const BlogPostsResponse({required this.message});

  factory BlogPostsResponse.fromJson(Map<String, dynamic> json) =>
      _$BlogPostsResponseFromJson(json);

  Map<String, dynamic> toJson() => _$BlogPostsResponseToJson(this);
}
