import 'package:didvan/models/content/content_item.dart'; class SwotItem { final int id; final String title; final String description; final String category; final String type; final String imageUrl; final double x1; final double y1; final String createdAt; /// uuid اصلی content-service (در محتوای جدید). در داده‌ی قدیمی null است. final String? keycloakId; SwotItem({ required this.id, required this.title, required this.description, required this.category, required this.type, required this.imageUrl, required this.x1, required this.y1, required this.createdAt, this.keycloakId, }); factory SwotItem.fromJson(Map json) { return SwotItem( id: json['id'], title: json['title'], description: json['description'], category: json['category'], type: json['type'], imageUrl: json["url"], x1: json["scoreX1"], y1: json["scoreY1"], createdAt: json["createdAt"] ); } /// ساختن SwotItem از ContentItem (دسته‌ی «فرصت و تهدید» در content-service). /// نوع (opportunity/threat) از `metadata.type` می‌آید. /// امتیازهای محور X و Y مستقیما از `metadata.x1`/`metadata.y1` خوانده /// می‌شوند (افق ۱ ساله — وزن‌دار شده در swot-service). اگر متادیتا خالی بود /// (محتوای legacy)، به parse جدول قدیمی fallback می‌شود. factory SwotItem.fromContentItem(ContentItem item) { // widget قدیمی با type == "THREAT" (uppercase) چک می‌کند. final isThreat = (item.metaType ?? '').toLowerCase() == 'threat'; final type = isThreat ? 'THREAT' : 'OPPORTUNITY'; double x1 = item.metaScoreX1; double y1 = item.metaScoreY1; if (x1 == 0 && y1 == 0) { final fallback = _extractScores(item.body); x1 = fallback.$1; y1 = fallback.$2; } return SwotItem( id: item.id.hashCode, keycloakId: item.id, title: item.title, description: item.summary ?? '', category: item.category?.name ?? 'فرصت و تهدید', type: type, imageUrl: item.coverImage ?? '', x1: x1, y1: y1, createdAt: item.publishedAt?.toIso8601String() ?? '', ); } /// در body یک بلوک table پیدا می‌کند و میانگینِ ستونِ آخر را برای محورهای /// X و Y برمی‌گرداند. اگر چیزی پیدا نشد، 0 برمی‌گرداند. static (double, double) _extractScores(dynamic body) { try { if (body is! Map) return (0.0, 0.0); final blocks = body['blocks']; if (blocks is! List) return (0.0, 0.0); for (final block in blocks) { if (block is! Map) continue; if (block['type'] != 'table') continue; final data = block['data']; if (data is! Map) continue; final content = data['content']; if (content is! List || content.isEmpty) continue; // ستونِ آخر = آخرین مقدار در آرایه‌ی هر سطر. double xSum = 0, ySum = 0; int xCount = 0, yCount = 0; for (var i = 1; i < content.length; i++) { final row = content[i]; if (row is! List || row.length < 3) continue; final axis = row[1]?.toString().toUpperCase().trim(); final last = row.last?.toString().trim(); final val = double.tryParse(last ?? ''); if (val == null) continue; if (axis == 'X') { xSum += val; xCount++; } else if (axis == 'Y') { ySum += val; yCount++; } } final x1 = xCount > 0 ? xSum / xCount : 0.0; final y1 = yCount > 0 ? ySum / yCount : 0.0; return (x1, y1); } } catch (_) {} return (0.0, 0.0); } }