import 'dart:convert';
import '../models/post_models.dart';
import '../models/comment_models.dart';
import 'http_service.dart';
import 'auth_service.dart';
import 'cache_service.dart';

class PostService {
  static bool _pollingStarted = false;
  static bool _userPostsPollingStarted = false;

  /// Get all posts with caching - returns cached data if available and fresh
  static Future<Map<String, dynamic>> getAllPosts({
    bool forceRefresh = false,
  }) async {
    // Return cached data if available and not forcing refresh
    if (!forceRefresh) {
      final cached = CacheService.getCached<List<Post>>(
        CacheService.postsAllKey,
      );
      if (cached != null &&
          !CacheService.isCacheExpired(
            CacheService.postsAllKey,
            CacheService.postsCacheDuration,
          )) {
        return {
          'success': true,
          'message': 'Loaded from cache',
          'posts': cached,
        };
      }

      // Return stale data while fetching fresh data in background
      final stale = CacheService.getCachedStale<List<Post>>(
        CacheService.postsAllKey,
      );
      if (stale != null && !forceRefresh) {
        // Trigger background refresh
        _fetchAndCachePosts();
        return {
          'success': true,
          'message': 'Loaded from cache (refreshing in background)',
          'posts': stale,
        };
      }
    }

    // Fetch fresh data
    return await _fetchAndCachePosts();
  }

  static Future<Map<String, dynamic>> _fetchAndCachePosts([bool fromPolling = false]) async {
    try {
      final response = await HttpService.get('/posts/all');

      if (response.statusCode == 200) {
        final responseData = jsonDecode(response.body);
        final posts =
            (responseData['data'] as List?)
                ?.map((post) => Post.fromJson(post))
                .toList() ??
            [];

        // Only cache when not called from polling to prevent conflicts
        if (!fromPolling) {
          CacheService.setCached(CacheService.postsAllKey, posts);
        }

        return {
          'success': responseData['status'] ?? false,
          'message': responseData['message'] ?? '',
          'posts': posts,
        };
      } else if (response.statusCode == 401 || response.statusCode == 403) {
        await AuthService.handleAuthenticationError();
        return {
          'success': false,
          'message': 'Session expired. Please login again.',
          'posts': <Post>[],
        };
      } else {
        try {
          final responseData = jsonDecode(response.body);
          return {
            'success': false,
            'message': responseData['message'] ?? 'Failed to fetch posts',
            'posts': <Post>[],
          };
        } catch (e) {
          return {
            'success': false,
            'message': 'Server error (${response.statusCode})',
            'posts': <Post>[],
          };
        }
      }
    } catch (e) {
      print('Error fetching posts: $e');
      return {
        'success': false,
        'message': 'Network error: $e',
        'posts': <Post>[],
      };
    }
  }

  /// Start background polling for posts
  static void startPolling() {
    _pollingStarted = true;
    CacheService.startPolling(
      CacheService.postsAllKey,
      () => _fetchAndCachePosts(true), // Mark as from polling
      CacheService.postsPollingInterval,
      CacheService.postsCacheDuration,
    );
  }

  /// Stop background polling for posts
  static void stopPolling() {
    CacheService.stopPolling(CacheService.postsAllKey);
    _pollingStarted = false;
  }

  /// Get posts stream for real-time updates
  static Stream<List<Post>> getPostsStream() {
    return CacheService.getStream<List<Post>>(CacheService.postsAllKey);
  }

  /// Force notify stream with current cached data (useful for initial stream setup)
  static void notifyStreamWithCurrentData() {
    final cached = CacheService.getCachedStale<List<Post>>(
      CacheService.postsAllKey,
    );
    if (cached != null) {
      // Re-notify the stream with current data
      CacheService.notifyStreamListeners<List<Post>>(
        CacheService.postsAllKey,
        cached,
      );
    }
  }

  /// Start background polling for user posts
  static void startUserPostsPolling() {
    _userPostsPollingStarted = true;
    CacheService.startPolling(
      CacheService.userPostsKey,
      () => _fetchAndCacheUserPosts(true), // Mark as from polling
      CacheService.userPostsPollingInterval,
      CacheService.userPostsCacheDuration,
    );
  }

  /// Stop background polling for user posts
  static void stopUserPostsPolling() {
    CacheService.stopPolling(CacheService.userPostsKey);
    _userPostsPollingStarted = false;
  }

  /// Get user posts stream for real-time updates
  static Stream<List<Post>> getUserPostsStream() {
    return CacheService.getStream<List<Post>>(CacheService.userPostsKey);
  }

  /// Force notify user posts stream with current cached data
  static void notifyUserPostsStreamWithCurrentData() {
    final cached = CacheService.getCachedStale<List<Post>>(
      CacheService.userPostsKey,
    );
    if (cached != null) {
      // Re-notify the stream with current data
      CacheService.notifyStreamListeners<List<Post>>(
        CacheService.userPostsKey,
        cached,
      );
    }
  }

  /// Check if polling is active
  static bool get isPollingActive => _pollingStarted;

  /// Check if user posts polling is active
  static bool get isUserPostsPollingActive => _userPostsPollingStarted;

  /// Invalidate posts cache (useful after creating/updating posts)
  static void invalidateCache() {
    CacheService.clearCache(CacheService.postsAllKey);
  }

  /// Invalidate user posts cache (useful after creating posts)
  static void invalidateUserPostsCache() {
    CacheService.clearCache(CacheService.userPostsKey);
  }

  /// Get user posts with caching - returns cached data if available and fresh
  static Future<Map<String, dynamic>> getUserPosts({
    bool forceRefresh = false,
  }) async {
    // Return cached data if available and not forcing refresh
    if (!forceRefresh) {
      final cached = CacheService.getCached<List<Post>>(
        CacheService.userPostsKey,
      );
      if (cached != null &&
          !CacheService.isCacheExpired(
            CacheService.userPostsKey,
            CacheService.userPostsCacheDuration,
          )) {
        return {
          'success': true,
          'message': 'Loaded from cache',
          'posts': cached,
        };
      }

      // Return stale data while fetching fresh data in background
      final stale = CacheService.getCachedStale<List<Post>>(
        CacheService.userPostsKey,
      );
      if (stale != null && !forceRefresh) {
        // Trigger background refresh
        _fetchAndCacheUserPosts();
        return {
          'success': true,
          'message': 'Loaded from cache (refreshing in background)',
          'posts': stale,
        };
      }
    }

    // Fetch fresh data
    return await _fetchAndCacheUserPosts();
  }

  static Future<Map<String, dynamic>> _fetchAndCacheUserPosts([bool fromPolling = false]) async {
    try {
      final response = await HttpService.get('/posts/user');

      final responseData = jsonDecode(response.body);

      if (response.statusCode == 200) {
        final posts = (responseData['data'] as List?)
                ?.map((post) => Post.fromJson(post))
                .toList() ??
            [];

        // Only cache when not called from polling to prevent conflicts
        if (!fromPolling) {
          CacheService.setCached(CacheService.userPostsKey, posts);
        }

        return {
          'success': responseData['status'] ?? false,
          'message': responseData['message'] ?? '',
          'posts': posts,
        };
      } else if (response.statusCode == 401 || response.statusCode == 403) {
        await AuthService.handleAuthenticationError();
        return {
          'success': false,
          'message': 'Session expired. Please login again.',
          'posts': <Post>[],
        };
      } else {
        return {
          'success': false,
          'message': responseData['message'] ?? 'Failed to fetch user posts',
          'posts': <Post>[],
        };
      }
    } catch (e) {
      print('Error fetching user posts: $e');
      return {
        'success': false,
        'message': 'Network error: $e',
        'posts': <Post>[],
      };
    }
  }

  static Future<Map<String, dynamic>> createPost(String body) async {
    try {
      final createPostRequest = CreatePostRequest(body: body);
      final response = await HttpService.post(
        '/posts/create',
        createPostRequest.toJson(),
      );

      final responseData = jsonDecode(response.body);

      if (response.statusCode == 200 || response.statusCode == 201) {
        // Invalidate both posts caches since we added a new post
        invalidateCache();
        invalidateUserPostsCache();

        return {
          'success': responseData['status'] ?? false,
          'message': responseData['message'] ?? '',
          'post': responseData['data'] != null
              ? Post.fromJson(responseData['data'])
              : null,
        };
      } else {
        return {
          'success': false,
          'message': responseData['message'] ?? 'Failed to create post',
          'post': null,
        };
      }
    } catch (e) {
      print('Error creating post: $e');
      return {'success': false, 'message': 'Network error: $e', 'post': null};
    }
  }

  static Future<Map<String, dynamic>> likePost(String postId) async {
    try {
      final response = await HttpService.post('/posts/like', {
        'postId': postId,
      });

      final responseData = jsonDecode(response.body);

      if (response.statusCode == 200) {
        return {
          'success': responseData['status'] ?? false,
          'message': responseData['message'] ?? '',
          'post': responseData['data'] != null
              ? Post.fromJson(responseData['data'])
              : null,
        };
      } else {
        return {
          'success': false,
          'message': responseData['message'] ?? 'Failed to like post',
          'post': null,
        };
      }
    } catch (e) {
      print('Error liking post: $e');
      return {'success': false, 'message': 'Network error: $e', 'post': null};
    }
  }

  static Future<Map<String, dynamic>> unlikePost(String postId) async {
    try {
      final response = await HttpService.post('/posts/unlike', {
        'postId': postId,
      });

      final responseData = jsonDecode(response.body);

      if (response.statusCode == 200) {
        return {
          'success': responseData['status'] ?? false,
          'message': responseData['message'] ?? '',
          'post': responseData['data'] != null
              ? Post.fromJson(responseData['data'])
              : null,
        };
      } else {
        return {
          'success': false,
          'message': responseData['message'] ?? 'Failed to unlike post',
          'post': null,
        };
      }
    } catch (e) {
      print('Error unliking post: $e');
      return {'success': false, 'message': 'Network error: $e', 'post': null};
    }
  }

  static Future<Map<String, dynamic>> getPost(String postId) async {
    try {
      final response = await HttpService.get('/posts/get?id=$postId');

      final responseData = jsonDecode(response.body);

      if (response.statusCode == 200) {
        return {
          'success': responseData['status'] ?? false,
          'message': responseData['message'] ?? '',
          'post': responseData['data'] != null
              ? DetailedPost.fromJson(responseData['data'])
              : null,
        };
      } else {
        return {
          'success': false,
          'message': responseData['message'] ?? 'Failed to fetch post',
          'post': null,
        };
      }
    } catch (e) {
      print('Error fetching post: $e');
      return {'success': false, 'message': 'Network error: $e', 'post': null};
    }
  }

  static Future<Map<String, dynamic>> getComments(String postId) async {
    try {
      final response = await HttpService.get(
        '/posts/comments/list?postId=$postId',
      );

      if (response.statusCode == 200) {
        final responseData = jsonDecode(response.body);
        final commentsResponse = CommentsResponse.fromJson(responseData);

        if (commentsResponse.status) {
          return {'success': true, 'comments': commentsResponse.data};
        } else {
          return {
            'success': false,
            'message': commentsResponse.message ?? 'Failed to fetch comments',
            'comments': <Comment>[],
          };
        }
      } else if (response.statusCode == 401 || response.statusCode == 403) {
        await AuthService.handleAuthenticationError();
        return {
          'success': false,
          'message': 'Session expired. Please login again.',
          'comments': <Comment>[],
        };
      } else {
        try {
          final responseData = jsonDecode(response.body);
          return {
            'success': false,
            'message': responseData['message'] ?? 'Failed to fetch comments',
            'comments': <Comment>[],
          };
        } catch (e) {
          return {
            'success': false,
            'message': 'Server error (${response.statusCode})',
            'comments': <Comment>[],
          };
        }
      }
    } catch (e) {
      print('Error fetching comments: $e');
      return {
        'success': false,
        'message': 'Network error: $e',
        'comments': <Comment>[],
      };
    }
  }

  static Future<Map<String, dynamic>> createComment({
    required String postId,
    required String body,
    String? replyComment,
  }) async {
    try {
      final requestBody = {'postId': int.parse(postId), 'body': body};

      if (replyComment != null) {
        requestBody['replyComment'] = int.parse(replyComment);
      }

      final response = await HttpService.post(
        '/posts/comments/create',
        requestBody,
      );

      if (response.statusCode == 200 || response.statusCode == 201) {
        final responseData = jsonDecode(response.body);

        if (responseData['status'] == true) {
          return {
            'success': true,
            'comment': Comment.fromJson(responseData['data']),
          };
        } else {
          return {
            'success': false,
            'message': responseData['message'] ?? 'Failed to create comment',
          };
        }
      } else if (response.statusCode == 401 || response.statusCode == 403) {
        await AuthService.handleAuthenticationError();
        return {
          'success': false,
          'message': 'Session expired. Please login again.',
        };
      } else {
        try {
          final responseData = jsonDecode(response.body);
          return {
            'success': false,
            'message': responseData['message'] ?? 'Failed to create comment',
          };
        } catch (e) {
          return {
            'success': false,
            'message': 'Server error (${response.statusCode})',
          };
        }
      }
    } catch (e) {
      print('Error creating comment: $e');
      return {'success': false, 'message': 'Network error: $e'};
    }
  }
}
