<?php

namespace App\Http\Controllers;

use App\Models\Page;
use App\Models\Poll;
use App\Models\Post;
use App\Models\User;
use App\Models\Group;
use App\Models\Comment;
use App\Models\Funding;
use App\Models\HashTag;
use App\Models\PostTag;
use App\Models\PollVote;
use App\Models\PostMedia;
use App\Models\PollOption;
use App\Models\GroupMember;
use App\Models\PostComment;
use Illuminate\Support\Str;
use App\Models\Notification;
use Illuminate\Http\Request;
use App\Services\RewardService;
use Illuminate\Support\FacadesDB;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\Controller;
use App\Http\Resources\PostResource;
use Illuminate\Support\Facades\Auth;
use App\Http\Resources\CommentResource;
use App\Http\Resources\UserShortResource;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;

class PostController extends Controller
{
    protected $rewardService;

    public function __construct(RewardService $rewardService)
    {
        $this->rewardService = $rewardService;
    }

    private function sanitizeGifUrl(?string $url): ?string
    {
        if (!$url) return null;
        $parsed = parse_url($url);
        if (!$parsed || empty($parsed['scheme']) || empty($parsed['host'])) {
            return null;
        }
        $host = strtolower($parsed['host']);
        // Allowlist trusted GIF providers and our own domain
        $allowedHosts = [
            'media.giphy.com',
            'giphy.com',
            'i.giphy.com',
            'tenor.com',
            'media.tenor.com',
            parse_url(config('app.url'), PHP_URL_HOST),
        ];
        foreach ($allowedHosts as $allowed) {
            if (!$allowed) continue;
            if ($host === $allowed || str_ends_with($host, '.' . $allowed)) {
                return $url;
            }
        }
        return null;
    }

    public function add_post(Request $request)
    {
        $validatedData = $request->validate([
            'post_text' => 'nullable|string',
            'privacy_level' => 'required|integer|in:1,2,3,4',
            'page_id' => 'nullable|integer',
            'group_id' => 'nullable|integer',
            'images.*' => 'nullable|file|image',
            'video' => 'nullable|file|mimetypes:video/mp4',
            'audio' => 'nullable|file|mimetypes:audio/mpeg,audio/wav,audio/webm,audio/ogg,audio/mp4,audio/aac,audio/x-m4a,audio/flac',
            'attachments.*' => 'nullable|file|max:51200',
            'poll_option' => 'nullable|string', // legacy: comma separated options
            'poll_question' => 'nullable|string|max:200', // new UI: question text
            'poll_options' => 'nullable|string', // new UI: JSON encoded options array
            'post_type' => 'required|string|in:post,page_post,group_post,event,product,offer,job,poll,donation,reel',
            'tagged_users' => 'nullable|string',
            'mentioned_users' => 'nullable|string',
            'feeling_type' => 'nullable|string',
            'bg_color' => 'nullable|string', // legacy
            'background_color' => 'nullable|string', // new UI explicit
            'text_color' => 'nullable|string',
            'font_size' => 'nullable|string|in:small,normal,large,extra-large',
            'feeling' => 'nullable|string',
            'post_location' => 'nullable|string',
            'post_color_id' => 'nullable|integer',
            'is_scheduled' => 'nullable|in:0,1',
            'scheduled_datetime' => 'nullable|date_format:Y-m-d\TH:i',
            'is_anonymous' => 'nullable|in:0,1',
            'tips_enabled' => 'nullable|in:0,1',
            // GIF fields
            'gif_id' => 'nullable|string|max:100',
            'gif_url' => 'nullable|url|max:512',
            'gif_title' => 'nullable|string|max:150',
            'width' => 'nullable|integer',
            'height' => 'nullable|integer',
            'event_id' => 'nullable|integer',
            'product_id' => 'nullable|integer',
            'feeling-category' => 'nullable|string',
            'feeling-description' => 'nullable|string',
            // Donation fields
            'amount' => 'nullable|numeric|min:0',
            'description' => 'nullable|string|max:1000',
            'donation_image' => 'nullable|file|image',
        ]);

        // Additional validation based on post_type
        $postType = $request->post_type;

        if ($postType === 'page_post' && !$request->filled('page_id')) {
            return response()->json([
                'status' => 422,
                'message' => __('Api.page_id_required_for_page_post')
            ], 422);
        }

        if ($postType === 'group_post' && !$request->filled('group_id')) {
            return response()->json([
                'status' => 422,
                'message' => __('Api.group_id_required_for_group_post')
            ], 422);
        }

        if ($postType === 'event' && !$request->filled('event_id')) {
            return response()->json([
                'status' => 422,
                'message' => __('Api.event_id_required_for_event_post')
            ], 422);
        }

        if ($postType === 'product' && !$request->filled('product_id')) {
            return response()->json([
                'status' => 422,
                'message' => __('Api.product_id_required_for_product_post')
            ], 422);
        }

        if ($postType === 'donation' && (!$request->filled('amount') || !$request->filled('description'))) {
            return response()->json([
                'status' => 422,
                'message' => __('Api.amount_and_description_required_for_donation_post')
            ], 422);
        }

        $user = Auth::user();

        $isPollCreateAttempt = $request->post_type === 'poll' && ($request->filled('poll_options') || $request->filled('poll_option'));
        if (empty($request->post_text) && empty($request->file('images')) && empty($request->file('video')) && empty($request->file('audio')) && !$isPollCreateAttempt) {
            return response()->json([
                'status' => 400,
                'message' => __('Api.input_required')
            ], 400);
        }


        // Validate page ownership
        if ($request->filled('page_id')) {
            $page = Page::find($request->page_id);

            if (!$page) {
                return response()->json([
                    'status' => 404,
                    'message' => __('Api.page_not_found') // Better response for non-existing pages
                ], 404);
            }

            if ($page->user_id !== $user->id) {
                return response()->json([
                    'status' => 403,
                    'message' => __('Api.unauthorized_access') // Page exists but user is not the owner
                ], 403);
            }
        }


        // Validate group membership
        if ($request->filled('group_id')) {
            $group = Group::with('members')->find($request->group_id);

            // Check if group exists
            if (!$group) {
                return response()->json([
                    'status' => 404,
                    'message' => __('Api.group_not_found')
                ], 404);
            }

            // Fetch the user's membership details
            $groupMember = GroupMember::where('group_id', $group->id)
                ->where('user_id', $user->id)
                ->first();

            // Check if the user is a group member
            if (!$groupMember) {
                return response()->json([
                    'status' => 403,
                    'message' => __('Api.not_a_group_member')
                ], 403);
            }

            // Get user's role in the group
            $userRole = $groupMember->role; // Values: 'admin', 'moderator', 'member'

            // If the group is private, only members should be allowed
            if ($group->is_private && !$groupMember) {
                return response()->json([
                    'status' => 403,
                    'message' => __('Api.private_group_no_access')
                ], 403);
            }

            // Allow admins and moderators to post without restrictions
            if ($userRole === 'admin' || $userRole === 'moderator') {
                // Admins and Moderators can post, continue execution
            } else {
                // Regular members need permission to post
                if (!$group->allow_members_to_post) {
                    return response()->json([
                        'status' => 403,
                        'message' => __('Api.members_cannot_post')
                    ], 403);
                }
            }
        }



        DB::beginTransaction();

        try {
            // Extract video URLs
            $youtubeUrl = '';
            $vimeoUrl = '';
            if ($request->filled('post_text')) {
                preg_match_all('/\bhttps?:\/\/(?:www\.)?(?:youtube\.com|youtu\.be|vimeo\.com)\/\S+\b/', $request->post_text, $matches);
                foreach ($matches[0] as $url) {
                    if (str_contains($url, 'youtube') && empty($youtubeUrl)) {
                        $youtubeUrl = $url;
                    } elseif (str_contains($url, 'vimeo') && empty($vimeoUrl)) {
                        $vimeoUrl = $url;
                    }
                }
            }
            $poll = null;
            $poll_id = 0; // Initialize poll_id to avoid undefined variable
            if ($request->post_type == 'poll') {
                // Determine poll title and options supporting both legacy and new UI payloads
                $pollTitle = $request->input('poll_question', $request->post_text);
                $pollTitle = censor_text($pollTitle);
                $optionsInput = [];
                if ($request->filled('poll_options')) {
                    // New UI sends JSON array of strings
                    try {
                        $decoded = json_decode($request->poll_options, true);
                        if (is_array($decoded)) {
                            $optionsInput = array_values(array_filter(array_map('trim', $decoded), fn($o) => $o !== ''));
                        }
                    } catch (\Throwable $e) {
                        // Fallback silently; validation below will handle empty options
                    }
                } elseif ($request->filled('poll_option')) {
                    // Legacy comma separated string
                    $optionsInput = array_values(array_filter(array_map('trim', explode(',', $request->poll_option)), fn($o) => $o !== ''));
                }

                if (!empty($optionsInput)) {
                    $optionsInput = array_map(static fn($option) => censor_text($option), $optionsInput);
                }

                if (!empty($optionsInput)) {
                    // Create a new poll
                    $poll = Poll::create([
                        'title' => $pollTitle,
                        'is_active' => true,
                    ]);
                    $poll_id = $poll->id;
                    // Save poll options
                    foreach ($optionsInput as $option) {
                        PollOption::create([
                            'poll_id' => $poll->id,
                            'option_text' => $option,
                        ]);
                    }
                }
            }
            // dd($request->all());
            // Create post
            // Sanitize GIF URL against allowlist
            $allowedGifUrl = null;
            if ($request->filled('gif_url')) {
                $allowedGifUrl = $this->sanitizeGifUrl($request->gif_url);
            }

            $postText = censor_text($request->post_text);

            $post = Post::create([
                'user_id' => $user->id,
                'post_text' => $postText,
                'privacy_level' => $request->privacy_level,
                'page_id' => $request->page_id ?? 0,
                'group_id' => $request->group_id ?? 0,
                'post_type' => $request->post_type ?? "",
                'ip_address' => $request->header('X-Forwarded-For') ?: $request->ip(),
                'location' => $request->post_location,
                // Color post fields
                'background_color' => $request->input('background_color', $request->input('bg_color')),
                'text_color' => $request->input('text_color'),
                'font_size' => $request->input('font_size', 'normal'),
                // GIF fields
                'gif_url' => $allowedGifUrl,
                'gif_title' => $allowedGifUrl ? $request->input('gif_title', '') : null,
                'gif_provider' => $allowedGifUrl ? parse_url($allowedGifUrl, PHP_URL_HOST) : null,
                'feeling' => $request->feeling,
                'post_color_id' => $request->post_color_id ?? 0,
                'width' => $request->width ?? 0,
                'height' => $request->height ?? 0,
                'event_id' => $request->event_id ?? 0,
                'product_id' => $request->product_id ?? 0,
                'youtube_urls' => $youtubeUrl,
                'vimeo_urls' => $vimeoUrl,
                'feeling_category' => $request->feeling_category ?? "",
                'feeling_description' => $request->feeling_description ?? "",
                'poll_id' => $poll_id,
                // Scheduling
                'scheduled_at' => ($request->input('is_scheduled') == '1' && $request->filled('scheduled_datetime')) ? \Carbon\Carbon::parse($request->input('scheduled_datetime')) : null,
                'is_published' => ($request->input('is_scheduled') == '1') ? false : true,
                'is_anonymous' => $request->input('is_anonymous') == '1',
                'tips_enabled' => $request->input('tips_enabled') == '1',
            ]);


            // Save tagged users if provided (expects JSON array of user IDs)
            if ($request->filled('tagged_people')) {
                try {
                    $ids = json_decode($request->input('tagged_people'), true);
                    if (is_array($ids) && count($ids) > 0) {
                        $validIds = array_filter(array_map('intval', $ids), fn($v) => $v > 0);
                        if (!empty($validIds)) {
                            DB::table('posts_tagged')->where('post_id', $post->id)->delete();
                            $now = now();
                            $rows = array_map(fn($uid) => [
                                'post_id' => $post->id,
                                'user_id' => $uid,
                                'created_at' => $now,
                                'updated_at' => $now,
                            ], $validIds);
                            DB::table('posts_tagged')->insert($rows);
                        }
                    }
                } catch (\Throwable $e) {
                    // ignore tagging errors to not block post creation
                }
            }
            $pattern = "/#(\w+)/";
            preg_match_all($pattern, $postText ?? '', $hashtags);

            $all_hashtags = $hashtags[0];
            $checkoldtag = HashTag::whereIn('name', $all_hashtags)->get();

            if (count($checkoldtag) > 0) {
                foreach ($checkoldtag as $hashtag) {
                    PostTag::create(['post_id' => $post->id, 'hashtag_id' => $hashtag->id]);
                }
            }
            $get_tags = $checkoldtag->pluck('name')->toArray();
            $nonExistingTags = array_diff($all_hashtags, $get_tags);
            if (count($nonExistingTags) > 0) {
                foreach ($nonExistingTags as $nonexisttag) {
                    if (trim($nonexisttag) !== '') {
                        $newhashtag = HashTag::create(['name' => $nonexisttag]);
                        PostTag::create(['post_id' => $post->id, 'hashtag_id' => $newhashtag->id]);
                    }
                }
            }


            $mediaData = [];
            if ($request->hasFile('images')) {
                foreach ($request->file('images') as $image) {
                    if ($image->isValid()) {
                        $mediaData[] = [
                            'post_id' => $post->id,
                            'user_id' => $user->id,
                            'image_or_video' => 1,
                            'media_path' => storeMedia($image, 'post_images'),
                            'mime_type' => $image->getMimeType(),
                            'original_name' => $image->getClientOriginalName(),
                            'file_size' => $image->getSize(),
                            'created_at' => now(),
                            'updated_at' => now()
                        ];
                    }
                }
            }
            if ($request->hasFile('video') && $request->file('video')->isValid()) {
                $mediaData[] = [
                    'post_id' => $post->id,
                    'user_id' => $user->id,
                    'image_or_video' => 2,
                    'media_path' => storeMedia($request->file('video'), 'post_videos'),
                    'mime_type' => $request->file('video')->getMimeType(),
                    'original_name' => $request->file('video')->getClientOriginalName(),
                    'file_size' => $request->file('video')->getSize(),
                    'created_at' => now(),
                    'updated_at' => now()
                ];
                $video_thumbnail = $request->file('video_thumbnail');
                if (!empty($video_thumbnail)) {
                    $video_thumbnail_url = storeMedia($video_thumbnail, 'video_thumbnail');
                    Post::where('id', $post->id)->update(['video_thumbnail' => $video_thumbnail_url]);
                }
            }
            if ($request->hasFile('audio') && $request->file('audio')->isValid()) {
                $mediaData[] = [
                    'post_id' => $post->id,
                    'user_id' => $user->id,
                    'image_or_video' => 3,
                    'media_path' => storeMedia($request->file('audio'), 'post_audio'),
                    'mime_type' => $request->file('audio')->getMimeType(),
                    'original_name' => $request->file('audio')->getClientOriginalName(),
                    'file_size' => $request->file('audio')->getSize(),
                    'created_at' => now(),
                    'updated_at' => now()
                ];
            }
            // Generic attachments (documents, archives, etc.)
            if ($request->hasFile('attachments')) {
                foreach ($request->file('attachments') as $file) {
                    if ($file->isValid()) {
                        $mediaData[] = [
                            'post_id' => $post->id,
                            'user_id' => $user->id,
                            'image_or_video' => 4, // file
                            // Use a path that includes 'document' so storeMedia picks correct type
                            'media_path' => storeMedia($file, 'post_documents'),
                            'mime_type' => $file->getMimeType(),
                            'original_name' => $file->getClientOriginalName(),
                            'file_size' => $file->getSize(),
                            'created_at' => now(),
                            'updated_at' => now()
                        ];
                    }
                }
            }

            if (!empty($mediaData)) {
                PostMedia::insert($mediaData);
            }

            if ($request->post_type == 'donation') {
                $funding = new Funding();
                $funding->donation_title = $postText;
                if ($request->hasFile('donation_image') && $request->file('donation_image')->isValid()) {
                    $funding->donation_image = storeMedia($request->file('donation_image'), 'post_donation');
                }
                $funding->amount = $request->amount;
                $funding->description = $request->description;
                $funding->save();
                Post::where('id', $post->id)->update(['fund_id' => $funding->id]);
            }
            $postTags = $postText;


            // Process reward for creating a post
            $this->rewardService->processReward(
                Auth::user(),
                'post_create',
                $post->id,
                ['post_type' => $post->post_type]
            );

            DB::commit();
            // dd($post->load('media', 'poll.options', 'taggedUsers', 'page', 'group'));
            return response()->json([
                'status' => 200,
                'message' => __('Api.post_created_success'),
                'data' => new PostResource($post->load('media', 'poll.options', 'taggedUsers', 'page', 'group'))
            ], 200);
        } catch (\Exception $e) {
            DB::rollBack();
            logger()->error('Post creation error: ' . $e->getMessage());

            return response()->json([
                'status' => 500,
                'message' => __('Api.error_occurred'),
                'error' => $e->getMessage()
            ], 500);
        }
    }



    // Save a post
    public function savePost(Request $request)
    {
        $validatedData = $request->validate([
            'post_id' => 'required|exists:posts,id',
        ]);

        $user = Auth::user();

        // Check if the post is already saved
        $exists = DB::table('posts_saved')
            ->where('post_id', $validatedData['post_id'])
            ->where('user_id', $user->id)
            ->exists();

        if ($exists) {
            return response()->json([
                'status' => 400,
                'message' => __('Api.post_already_saved'),
            ], 400);
        }

        // Save the post
        DB::table('posts_saved')->insert([
            'post_id' => $validatedData['post_id'],
            'user_id' => $user->id,
            'created_at' => now(),
            'updated_at' => now(),
        ]);

        return response()->json([
            'status' => 200,
            'message' => __('Api.post_saved_successfully'),
        ], 200);
    }

    // Get saved posts
    public function getSavedPosts(Request $request)
    {
        $user = Auth::user();

        $savedPosts = Post::whereIn('id', function ($query) use ($user) {
            $query->select('post_id')
                ->from('posts_saved')
                ->where('user_id', $user->id);
        })
            ->with(['media', 'poll.options', 'parentPost.user', 'parentPost.media', 'parentPost.poll.options', 'taggedUsers']) // Ensure related data is eager-loaded
            ->paginate($request->get('per_page', 10));

        return response()->json([
            'status' => 200,
            'message' => __('Api.posts_saved_fetched_successfully'),
            'data' => PostResource::collection($savedPosts), // Use collection for multiple resources
        ], 200);
    }



    /**
     * Update the specified post in storage.
     */
    public function updatePost(Request $request, $id)
    {
        $user = Auth::user();

        // Validate request data
        $validatedData = $request->validate([
            'post_text' => 'nullable|string',
            'privacy_level' => 'nullable|integer|in:1,2,3,4',
            'page_id' => 'nullable|integer',
            'group_id' => 'nullable|integer',
            'images.*' => 'nullable|file|image',
            'video' => 'nullable|file|mimetypes:video/mp4',
            'audio' => 'nullable|file|mimetypes:audio/mpeg,audio/wav,audio/webm,audio/ogg,audio/mp4,audio/aac,audio/x-m4a,audio/flac',
            'feeling_type' => 'nullable|string',
            'bg_color' => 'nullable|string',
            'feeling' => 'nullable|string',
            'post_location' => 'nullable|string',
            'post_color_id' => 'nullable|integer',
        ]);

        // Fetch the post
        $post = Post::findOrFail($id);

        // Ensure the current user is the owner of the post
        if ($post->user_id !== $user->id) {
            return response()->json([
                'status' => 403,
                'message' => __('Api.unauthorized_to_update_post'),
            ], 403);
        }

        DB::beginTransaction();

        try {
            // Update post fields
            if ($request->has('post_text')) {
                $post->post_text = censor_text($request->input('post_text'));
            }
            $post->privacy_level = $request->input('privacy_level', $post->privacy_level);
            $post->page_id = $request->input('page_id', $post->page_id);
            $post->group_id = $request->input('group_id', $post->group_id);
            $post->feeling_category = $request->input('feeling_category', $post->feeling_category);
            $post->background_color = $request->input('background_color', $post->background_color);
            // $post->feeling = $request->input('feeling', $post->feeling);
            // $post->post_location = $request->input('post_location', $post->post_location);
            // $post->post_color_id = $request->input('post_color_id', $post->post_color_id);

            // Handle media updates
            // $mediaData = [];
            // if ($request->hasFile('images')) {
            //     foreach ($request->file('images') as $image) {
            //         if ($image->isValid()) {
            //             $mediaData[] = [
            //                 'post_id' => $post->id,
            //                 'user_id' => $user->id,
            //                 'image_or_video' => 1,
            //                 'media_path' => storeMedia($image, 'post_images'),
            //                 'created_at' => now(),
            //                 'updated_at' => now(),
            //             ];
            //         }
            //     }
            // }

            // if ($request->hasFile('video') && $request->file('video')->isValid()) {
            //     $mediaData[] = [
            //         'post_id' => $post->id,
            //         'user_id' => $user->id,
            //         'image_or_video' => 2,
            //         'media_path' => storeMedia($request->file('video'), 'post_videos'),
            //         'created_at' => now(),
            //         'updated_at' => now(),
            //     ];
            // }

            // if ($request->hasFile('audio') && $request->file('audio')->isValid()) {
            //     $mediaData[] = [
            //         'post_id' => $post->id,
            //         'user_id' => $user->id,
            //         'image_or_video' => 3,
            //         'media_path' => storeMedia($request->file('audio'), 'post_audio'),
            //         'created_at' => now(),
            //         'updated_at' => now(),
            //     ];
            // }

            // // Insert new media into the database
            // if (!empty($mediaData)) {
            //     PostMedia::insert($mediaData);
            // }

            // Save the updated post
            $post->save();

            DB::commit();

            return response()->json([
                'status' => 200,
                'message' => __('Api.post_updated_successfully'),
                'data' => new PostResource($post->load('media')),
            ], 200);
        } catch (\Exception $e) {
            DB::rollBack();
            logger()->error('Post update error: ' . $e->getMessage());

            return response()->json([
                'status' => 500,
                'message' => __('Api.error_occurred'),
                'error' => config('app.debug') ? $e->getMessage() : null,
            ], 500);
        }
    }

    public function getNewsfeed(Request $request)
    {
        $user = Auth::user();

        // Validate inputs
        $validated = $request->validate([
            'post_id' => 'nullable|integer|exists:posts,id',
            'offset' => 'nullable|integer|min:0',
            'limit' => 'nullable|integer|min:1|max:100',
            'post_type' => 'nullable|string',
            'group_id' => 'nullable|integer',
            'page_id' => 'nullable|integer',
            'user_id' => 'nullable|integer'
        ]);

        try {
            // If a post_id is provided, return only that post with privacy checks
            if (!empty($validated['post_id'])) {
                $post = Post::where('id', $validated['post_id'])
                    ->where(function ($query) use ($user) {
                        $this->applyPrivacyFilters($query, $user);
                    })
                    ->first();

                if (!$post) {
                    return response()->json([
                        'status' => 404,
                        'message' => __('Api.post_not_found'),
                    ], 404);
                }

                return response()->json([
                    'status' => 200,
                    'message' => __('Api.post_fetched_successfully'),
                    'data' => [new PostResource($post)],
                ], 200);
            }

            // Build the main query for the newsfeed
            $query = Post::query();

            // Get IDs for relationships
            $friendIds = $this->getFriendIds($user);

            $followingIds = $this->getFollowingIds($user);
            $likedPageIds = $this->getLikedPageIds($user);
            $joinedGroupIds = $this->getJoinedGroupIds($user);
            $familyMemberIds = $this->getFamilyMemberIds($user);


            // Handle specific post types and filters
            if (!empty($validated['post_type'])) {
                if ($validated['post_type'] == 'reel') {
                    $query->where('post_type', 'reel');
                } else {
                    $query->where('post_type', $validated['post_type'])->where('post_type', '!=', 'reel');

                    // Filter by page_id if provided and relevant
                    if ($validated['post_type'] === 'page_post' && !empty($validated['page_id'])) {
                        $query->where('page_id', $validated['page_id']);
                    }
                    // Filter by group_id if provided and relevant
                    else if ($validated['post_type'] === 'group_post' && !empty($validated['group_id'])) {
                        $query->where('group_id', $validated['group_id']);
                    }
                }
            } else if (!empty($validated['user_id'])) {
                $query->where('user_id', $validated['user_id'])->where('post_type', '!=', 'reel');
            }
            // Default newsfeed query with all content sources
            else {
                $query->where(function ($q) use ($user, $friendIds, $followingIds, $likedPageIds, $joinedGroupIds, $familyMemberIds) {
                    // User's own posts
                    $q->where('user_id', $user->id)->where('post_type', '!=', 'reel');


                    // Friend's posts
                    if (!empty($friendIds)) {
                        $q->orWhereIn('user_id', $friendIds)->where('post_type', '!=', 'reel');
                    }

                    // Family member's posts (if applicable)
                    if (!empty($familyMemberIds)) {
                        $q->orWhereIn('user_id', $familyMemberIds)->where('post_type', '!=', 'reel');
                    }

                    // Following users' posts
                    if (!empty($followingIds)) {
                        $q->orWhereIn('user_id', $followingIds)->where('post_type', '!=', 'reel');
                    }

                    // Liked pages' posts
                    if (!empty($likedPageIds)) {
                        $q->orWhereIn('page_id', $likedPageIds)->where('post_type', '!=', 'reel');
                    }

                    // Joined groups' posts
                    if (!empty($joinedGroupIds)) {
                        $q->orWhereIn('group_id', $joinedGroupIds)->where('post_type', '!=', 'reel');
                    }

                    // Include posts from verified/popular users that might be interesting
                    // (This is optional and depends on your business logic)
                    $q->orWhere(function ($popularQ) {
                        $popularQ->where('privacy_level', 1)->where('post_type', '!=', 'reel'); // Only public posts
                    });
                });
            }

            // Apply privacy filters for the current user
            $query->where(function ($privacyQuery) use ($user, $friendIds, $followingIds, $familyMemberIds) {
                $this->applyPrivacyFilters($privacyQuery, $user, $friendIds, $followingIds, $familyMemberIds);
            });

            // Handle boosted/sponsored posts (if applicable)
            $this->includeSponsoredContent($query, $user);

            // Sort by relevance or time (default to most recent)
            if (!empty($validated['sort_by']) && $validated['sort_by'] === 'relevance') {
                // Implement relevance sorting logic if needed
                $query->orderBy('engagement_score', 'desc')
                    ->orderBy('created_at', 'desc');
            } else {
                $query->orderBy('created_at', 'desc');
            }

            // Apply pagination
            $offset = $validated['offset'] ?? 0;
            $limit = $validated['limit'] ?? 10;

            // Execute query with eager loading
            // Exclude scheduled (unpublished) posts
            $query->where(function ($q) {
                $q->whereNull('scheduled_at')->orWhere('is_published', true)->orWhere('scheduled_at', '<=', now());
            });
            $posts = $query->with(['user', 'media', 'poll.options', 'parentPost.user', 'parentPost.media', 'parentPost.poll.options', 'taggedUsers', 'page', 'group'])
                ->skip($offset)
                ->take($limit)
                ->get();
            // Load event relationships only for event posts
            $eventPosts = $posts->where('post_type', 'event');
            if ($eventPosts->isNotEmpty()) {
                $eventPosts->load(['event.organizer', 'event.participants']);
            }

            // Load product relationships only for product posts
            $productPosts = $posts->where('post_type', 'product');
            if ($productPosts->isNotEmpty()) {
                $productPosts->load(['product.user', 'product.media', 'product.store', 'product.category']);
            }


            $postResources = PostResource::collection($posts);
            // print_r($postResources);
            // exit();
            return response()->json([
                'status' => 200,
                'message' => __('Api.newsfeed_fetched_successfully'),
                'data' => $postResources,
            ], 200);
        } catch (\Exception $e) {
            logger()->error('Error fetching newsfeed: ' . $e->getMessage());

            return response()->json([
                'status' => 500,
                'message' => __('Api.error_occurred'),
                'error' => config('app.debug') ? $e->getMessage() : null,
            ], 500);
        }
    }

    /**
     * Apply privacy filters to a query
     */
    private function applyPrivacyFilters($query, $user, $friendIds = null, $followingIds = null, $familyMemberIds = null)
    {
        // Always include public posts
        $query->where('privacy_level', 1);

        // Include user's own posts (regardless of privacy)
        $query->orWhere('user_id', $user->id);

        // Include friends-only posts from friends
        if ($friendIds === null) {
            $friendIds = $this->getFriendIds($user);
        }
        if (!empty($friendIds)) {
            $query->orWhere(function ($q) use ($friendIds) {
                $q->where('privacy_level', 2)
                    ->whereIn('user_id', $friendIds);
            });
        }

        // Include family-only posts (if applicable and family relationship exists)
        if ($familyMemberIds === null) {
            $familyMemberIds = $this->getFamilyMemberIds($user);
        }
        if (!empty($familyMemberIds)) {
            $query->orWhere(function ($q) use ($familyMemberIds) {
                $q->where('privacy_level', 5) // Assuming 5 is for family-only
                    ->whereIn('user_id', $familyMemberIds);
            });
        }

        // Include followers-only posts from users being followed
        if ($followingIds === null) {
            $followingIds = $this->getFollowingIds($user);
        }
        if (!empty($followingIds)) {
            $query->orWhere(function ($q) use ($followingIds) {
                $q->where('privacy_level', 4)
                    ->whereIn('user_id', $followingIds);
            });
        }
    }

    /**
     * Get IDs of the user's friends
     */
    private function getFriendIds($user)
    {
        // Use the existing getFriends method if it's already available
        $friends = User::getFriends($user->id);
        return $friends->map(function ($friend) use ($user) {
            return $friend->friend_one == $user->id ? $friend->friend_two : $friend->friend_one;
        })->toArray();
    }

    /**
     * Get IDs of users that the current user is following
     */
    private function getFollowingIds($user)
    {
        // Assuming there's a followers relationship
        // If not, you need to implement this based on your database structure
        try {
            return DB::table('followers')
                ->where('follower_id', $user->id)
                ->pluck('following_id')
                ->toArray();
        } catch (\Exception $e) {
            return [];
        }
    }

    /**
     * Get IDs of pages liked by the user
     */
    private function getLikedPageIds($user)
    {
        try {
            return DB::table('page_likes')
                ->where('user_id', $user->id)
                ->pluck('page_id')
                ->toArray();
        } catch (\Exception $e) {
            return [];
        }
    }

    /**
     * Get IDs of groups joined by the user
     */
    private function getJoinedGroupIds($user)
    {
        try {
            return DB::table('group_members')
                ->where('user_id', $user->id)
                ->where('status', 'accepted') // Only include groups where membership is confirmed
                ->pluck('group_id')
                ->toArray();
        } catch (\Exception $e) {
            return [];
        }
    }

    /**
     * Get IDs of family members
     */
    private function getFamilyMemberIds($user)
    {
        try {
            return DB::table('family_relationships')
                ->where('user_id', $user->id)
                ->orWhere('related_user_id', $user->id)
                ->get()
                ->map(function ($relationship) use ($user) {
                    return $relationship->user_id == $user->id ?
                        $relationship->related_user_id : $relationship->user_id;
                })
                ->toArray();
        } catch (\Exception $e) {
            return [];
        }
    }

    /**
     * Include sponsored or boosted content in the feed
     */
    private function includeSponsoredContent($query, $user)
    {
        // This is optional and depends on your business model
        // Here's a simple implementation that includes sponsored posts
        // try {
        //     $sponsoredPostIds = DB::table('sponsored_posts')
        //         ->where('status', 'active')
        //         ->where('end_date', '>=', now())
        //         ->where(function ($q) use ($user) {
        //             // Target based on demographics, interests, etc.
        //             $q->whereNull('target_audience') // Global campaigns
        //               ->orWhere('target_audience', 'like', '%' . $user->age_group . '%')
        //               ->orWhere('target_audience', 'like', '%' . $user->gender . '%')
        //               ->orWhere('target_audience', 'like', '%' . $user->location . '%');
        //         })
        //         ->pluck('post_id')
        //         ->toArray();

        //     if (!empty($sponsoredPostIds)) {
        //         $query->orWhereIn('id', $sponsoredPostIds);
        //     }
        // } catch (\Exception $e) {
        //     // If there's an error, just continue without sponsored content
        //     logger()->error('Error fetching sponsored content: ' . $e->getMessage());
        // }
    }

    public function getPostDetail($id)
    {
        try {
            // Fetch the post with relationships
            $post = Post::with(['user', 'media', 'poll.options', 'parentPost.user', 'parentPost.media', 'parentPost.poll.options', 'taggedUsers'])->find($id);

            // Check if the post exists
            if (!$post) {
                return response()->json([
                    'status' => 404,
                    'message' => __('Api.post_not_found'),
                ], 404);
            }


            // Return the response using PostResource
            return response()->json([
                'status' => 200,
                'message' => __('Api.post_fetched_successfully'),
                'data' => new PostResource($post),
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 500,
                'message' => __('Api.error_occurred'),
                'error' => config('app.debug') ? $e->getMessage() : null,
            ], 500);
        }
    }




    /**
     * Increment the view count for a post.
     */
    public function incrementViewCount($id)
    {
        $post = Post::findOrFail($id);

        $post->increment('views_count');

        return response()->json(['message' => 'View count incremented.', 'views_count' => $post->views_count]);
    }

    public function postAction(Request $request)
    {
        // Validate input data
        $validatedData = $request->validate([
            'post_id' => 'required|integer|exists:posts,id',
            'action' => 'required|string|in:like,dislike,save,delete,report,disablecomments,disabletips,share,reaction,poll_vote,tip',
            'reaction_type' => 'nullable|integer|in:0,1,2,3,4,5,6', // 0=None,  1=Like, 2=Love, 3=Haha, 4=Wow, 5=Sad, 6=Angry
            'reason' => 'nullable|string|min:3|max:255', // Minimum 3 characters for report reason
            'option_id' => 'nullable|integer|exists:poll_options,id',
            'amount' => 'nullable|numeric|min:0.1',
            'shared_text' => 'nullable'
        ]);

        $user = Auth::user();

        // Fetch the post safely
        $post = Post::find($validatedData['post_id']);
        if (!$post) {
            return response()->json([
                'status' => 404,
                'message' => __('Api.post_not_found')
            ], 404);
        }

        $action = $validatedData['action'];

        // Use transactions where necessary to ensure atomicity
        DB::beginTransaction();

        try {
            switch ($action) {
                case 'like':
                    // Use reaction type 1 (Like) for the like action
                    $response = $this->reactToPost($user, $post, 1);
                    break;

                case 'dislike':
                    // Use reaction type 5 (Sad) for the dislike action or another appropriate one
                    // You might want to customize which reaction type represents a dislike based on your requirements
                    $response = $this->reactToPost($user, $post, 5);
                    break;

                case 'save':
                    $response = $this->toggleSave($user, $post);
                    break;

                case 'delete':
                    $response = $this->deletePost($user, $post);
                    break;

                case 'report':
                    if (!isset($validatedData['reason']) || empty(trim($validatedData['reason']))) {
                        return response()->json([
                            'status' => 422,
                            'message' => __('Api.report_reason_required')
                        ], 422);
                    }
                    $response = $this->reportPost($user, $post, $validatedData['reason']);
                    break;

                case 'disablecomments':
                    $response = $this->toggleComments($user, $post);
                    break;

                case 'share':
                    $response = $this->sharePost($user, $post, $validatedData['shared_text']);
                    break;

                case 'reaction':
                    if (!isset($validatedData['reaction_type'])) {
                        return response()->json([
                            'status' => 422,
                            'message' => __('Api.reaction_type_required')
                        ], 422);
                    }
                    $response = $this->reactToPost($user, $post, $validatedData['reaction_type']);
                    break;

                case 'poll_vote':
                    if (!$post->poll_id) {
                        return response()->json([
                            'status' => 400,
                            'message' => 'This post is not a poll.'
                        ], 400);
                    }
                    if (!isset($validatedData['option_id'])) {
                        return response()->json([
                            'status' => 422,
                            'message' => 'option_id is required.'
                        ], 422);
                    }
                    $response = $this->votePoll($user, $post, (int)$validatedData['option_id']);
                    break;

                case 'disabletips':
                    $response = $this->toggleTips($user, $post);
                    break;

                case 'tip':
                    if (!$post->tips_enabled) {
                        return response()->json(['status' => 400, 'message' => 'Tips are disabled for this post'], 400);
                    }
                    if (!isset($validatedData['amount'])) {
                        return response()->json(['status' => 422, 'message' => 'Tip amount required'], 422);
                    }
                    $response = $this->tipPostAuthor($user, $post, (float)$validatedData['amount']);
                    break;

                default:
                    return response()->json([
                        'status' => 400,
                        'message' => __('Api.invalid_action')
                    ], 400);
            }


            DB::commit();
            return $response;
        } catch (\Exception $e) {
            DB::rollBack();



            return response()->json([
                'status' => 500,
                'message' => __('Api.error_occurred'),
                'error' => config('app.debug') ? $e->getMessage() : null
            ], 500);
        }
    }

    private function toggleSave($user, $post)
    {
        // Ensure post exists
        if (!$post) {
            return response()->json([
                'status' => 404,
                'message' => __('Api.post_not_found')
            ], 404);
        }

        DB::beginTransaction();

        try {
            // Check if post is already saved
            $existingSave = DB::table('posts_saved')
                ->where('post_id', $post->id)
                ->where('user_id', $user->id)
                ->first();

            if ($existingSave) {
                // Remove saved post
                DB::table('posts_saved')->where('id', $existingSave->id)->delete();

                DB::commit();

                // Clear cache if caching is enabled for saved posts
                // Cache::forget("user_{$user->id}_saved_posts");

                return response()->json([
                    'status' => 200,
                    'message' => __('Api.post_unsaved'),
                    'type' => 0,
                    'saved_at' => null
                ]);
            } else {
                // Save the post
                $saved_at = now();
                DB::table('posts_saved')->insert([
                    'post_id' => $post->id,
                    'user_id' => $user->id,
                    'created_at' => $saved_at
                ]);

                DB::commit();


                return response()->json([
                    'status' => 200,
                    'message' => __('Api.post_saved'),
                    'type' => 1,
                    'saved_at' => $saved_at
                ]);
            }
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'status' => 500,
                'message' => __('Api.error_occurred'),
                'error' => config('app.debug') ? $e->getMessage() : null
            ], 500);
        }
    }

    private function deletePost($user, $post)
    {
        if ($post->user_id !== $user->id) {
            return response()->json([
                'status' => 400,
                'message' => __('Api.unauthorized_delete')
            ], 400);
        }

        $postModel = new Post();
        $postModel->deletePosts([$post->id]);
        return response()->json([
            'status' => 200,
            'message' => __('Api.post_deleted')
        ]);
    }

    private function reportPost($user, $post, $reason)
    {
        DB::beginTransaction();

        try {
            // Validate if the post exists
            if (!$post) {
                return response()->json([
                    'status' => 404,
                    'message' => __('Api.post_not_found')
                ], 404);
            }

            // Check if the user has already reported this post
            $existingReport = DB::table('posts_report')
                ->where('post_id', $post->id)
                ->where('user_id', $user->id)
                ->first();

            if ($existingReport) {
                return response()->json([
                    'status' => 400,
                    'message' => __('Api.post_already_reported')
                ], 400);
            }

            // Ensure a valid reason is provided
            if (empty($reason) || strlen($reason) < 3) {
                return response()->json([
                    'status' => 422,
                    'message' => __('Api.invalid_report_reason')
                ], 422);
            }

            // Insert the report into the database
            DB::table('posts_report')->insert([
                'post_id' => $post->id,
                'user_id' => $user->id,
                'reason' => $reason,
                'created_at' => now()
            ]);

            DB::commit();

            return response()->json([
                'status' => 200,
                'message' => __('Api.post_reported'),
                'data' => [
                    'post_id' => $post->id,
                    'user_id' => $user->id,
                    'reason' => $reason
                ]
            ], 200);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'status' => 500,
                'message' => __('Api.error_occurred'),
                'error' => config('app.debug') ? $e->getMessage() : null
            ], 500);
        }
    }


    private function toggleComments($user, $post)
    {

        // Check if the user is the post owner
        if ($post->user_id !== $user->id) {
            return response()->json([
                'status' => 403,
                'message' => __('Api.unauthorized_action')
            ], 403);
        }

        DB::beginTransaction();

        try {
            // Toggle comments status (1 -> 0, 0 -> 1)
            $post->comments_status = !$post->comments_status;
            $post->save();

            DB::commit();


            return response()->json([
                'status' => 200,
                'message' => $post->comments_status ? __('Api.comments_enabled') : __('Api.comments_disabled'),
                'type' => $post->comments_status,
                'updated_at' => $post->updated_at
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'status' => 500,
                'message' => __('Api.error_occurred'),
                'error' => config('app.debug') ? $e->getMessage() : null
            ], 500);
        }
    }

    private function toggleTips($user, $post)
    {
        // Only post owner can toggle
        if ($post->user_id !== $user->id) {
            return response()->json([
                'status' => 403,
                'message' => __('Api.unauthorized_action')
            ], 403);
        }

        DB::beginTransaction();
        try {
            $post->tips_enabled = !$post->tips_enabled;
            $post->save();

            DB::commit();
            return response()->json([
                'status' => 200,
                'message' => $post->tips_enabled ? 'Tips enabled' : 'Tips disabled',
                'type' => $post->tips_enabled,
                'updated_at' => $post->updated_at
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'status' => 500,
                'message' => __('Api.error_occurred'),
                'error' => config('app.debug') ? $e->getMessage() : null
            ], 500);
        }
    }


    private function sharePost($user, $post, $shared_text)
    {


        // Prevent sharing a private post (if privacy settings exist)
        if ($post->privacy_level === 3 && $post->user_id !== $user->id) {
            return response()->json([
                'status' => 403,
                'message' => __('Api.post_not_shareable_due_to_privacy')
            ], 403);
        }

        // Prevent infinite loop of sharing shared posts
        if ($post->post_type === 'shared_post') {
            return response()->json([
                'status' => 400,
                'message' => __('Api.cannot_share_shared_post')
            ], 400);
        }

        DB::beginTransaction();

        try {
            // Create the shared post
            $sharedPost = $post->replicate();
            $sharedPost->user_id = $user->id;
            $sharedPost->shared_text = $shared_text;
            $sharedPost->post_type = 'shared_post'; // Mark as a shared post
            $sharedPost->parent_post_id = $post->id; // Keep track of the parent post
            $sharedPost->shared_at = now();
            $sharedPost->save();
            $userdata = User::select('device_id', 'notification_setting')
                ->where('id', $post->user_id)
                ->first(); // Make sure to use first() to get a single result

            if (!empty($userdata) && $user->id != $post->user_id) {
                // Decode the JSON column and access the 'notify_like' value
                $notificationSharePost = json_decode(str_replace("\xc2\xa0", ' ', $userdata->notification_setting))->notify_share_post;
                if ($notificationSharePost == 1) {
                    Notification::create([
                        'from_user_id' => $user->id,
                        'to_user_id' => $post->user_id,
                        'type' => 'share_post',
                        'text' => 'share your post',
                        'post_id' => $post->id,
                    ]);
                    if (!empty($userdata->device_id)) {
                        sendFirebaseNotification($userdata->device_id, 'Post Shared ', $user->username . ' shared  your post');
                    }
                }
            }


            // Increment original post share count
            $post->increment('shares_count');

            DB::commit();

            return response()->json([
                'status' => 200,
                'message' => __('Api.post_shared'),
                'data' => new PostResource($sharedPost),
                'shared_at' => $sharedPost->shared_at
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'status' => 500,
                'message' => __('Api.error_occurred'),
                'error' => config('app.debug') ? $e->getMessage() : null
            ], 500);
        }
    }



    private function reactToPost($user, $post, $reactionType)
    {
        $existingReaction = DB::table('posts_reactions')
            ->where('post_id', $post->id)
            ->where('user_id', $user->id)
            ->first();

        if ($existingReaction) {
            $this->rewardService->processReward(
                $user,
                'post_reaction',
                $post->id,
                ['action' =>  $reactionType]
            );

            if ($existingReaction->reaction == $reactionType) {
                DB::table('posts_reactions')->where('id', $existingReaction->id)->delete();

                // Get total reactions count for this post
                $totalReactions = DB::table('posts_reactions')
                    ->where('post_id', $post->id)
                    ->count();

                // Get count for this specific reaction type
                $typeCount = DB::table('posts_reactions')
                    ->where('post_id', $post->id)
                    ->where('reaction', $reactionType)
                    ->count();

                return response()->json([
                    'status' => 200,
                    'message' => __('Api.reaction_removed'),
                    'type' => 0,
                    'reaction_type' => $reactionType,
                    'reaction_count' => $typeCount,
                    'total_reactions' => $totalReactions,
                    'is_reacted' => 0,
                    'reaction_counts' => [
                        'like' => DB::table('posts_reactions')->where('post_id', $post->id)->where('reaction', 1)->count(),
                        'love' => DB::table('posts_reactions')->where('post_id', $post->id)->where('reaction', 2)->count(),
                        'haha' => DB::table('posts_reactions')->where('post_id', $post->id)->where('reaction', 3)->count(),
                        'wow' => DB::table('posts_reactions')->where('post_id', $post->id)->where('reaction', 4)->count(),
                        'sad' => DB::table('posts_reactions')->where('post_id', $post->id)->where('reaction', 5)->count(),
                        'angry' => DB::table('posts_reactions')->where('post_id', $post->id)->where('reaction', 6)->count(),
                    ],
                ]);
            }

            DB::table('posts_reactions')
                ->where('post_id', $post->id)
                ->where('user_id', $user->id)
                ->update(['reaction' => $reactionType]);

            // Get total reactions count for this post
            $totalReactions = DB::table('posts_reactions')
                ->where('post_id', $post->id)
                ->count();

            // Get count for this specific reaction type
            $typeCount = DB::table('posts_reactions')
                ->where('post_id', $post->id)
                ->where('reaction', $reactionType)
                ->count();

            return response()->json([
                'status' => 200,
                'message' => __('Api.reaction_updated'),
                'type' => 1,
                'reaction_type' => $reactionType,
                'reaction_count' => $typeCount,
                'total_reactions' => $totalReactions,
                'is_reacted' => 1,
                'reaction_counts' => [
                    'like' => DB::table('posts_reactions')->where('post_id', $post->id)->where('reaction', 1)->count(),
                    'love' => DB::table('posts_reactions')->where('post_id', $post->id)->where('reaction', 2)->count(),
                    'haha' => DB::table('posts_reactions')->where('post_id', $post->id)->where('reaction', 3)->count(),
                    'wow' => DB::table('posts_reactions')->where('post_id', $post->id)->where('reaction', 4)->count(),
                    'sad' => DB::table('posts_reactions')->where('post_id', $post->id)->where('reaction', 5)->count(),
                    'angry' => DB::table('posts_reactions')->where('post_id', $post->id)->where('reaction', 6)->count(),
                ],
            ]);
        }

        DB::table('posts_reactions')->insert([
            'post_id' => $post->id,
            'user_id' => $user->id,
            'reaction' => $reactionType,
            'created_at' => now()
        ]);

        // Get total reactions count for this post
        $totalReactions = DB::table('posts_reactions')
            ->where('post_id', $post->id)
            ->count();

        // Get count for this specific reaction type
        $typeCount = DB::table('posts_reactions')
            ->where('post_id', $post->id)
            ->where('reaction', $reactionType)
            ->count();
        $userdata = User::select('device_id', 'notification_setting')
            ->where('id', $post->user_id)
            ->first(); // Make sure to use first() to get a single result

        if ($userdata && $user->id != $post->user_id) {
            $notifyLike = json_decode(str_replace("\xc2\xa0", ' ', $userdata->notification_setting))->notify_like;
            if ($notifyLike == 1) {
                Notification::create([
                    'from_user_id' => $user->id,
                    'to_user_id' => $post->user_id,
                    'type' => 'post_reaction',
                    'post_id' => $post->id,
                    'text' => 'reacted on your post.',
                ]);
                if (!empty($userdata->device_id)) {
                    sendFirebaseNotification($userdata->device_id, 'Reaction on Post', $user->username . ' reacted on your post');
                }
            }
        }
        return response()->json([
            'status' => 200,
            'message' => __('Api.reaction_added'),
            'type' => 1,
            'reaction_type' => $reactionType,
            'reaction_count' => $typeCount,
            'total_reactions' => $totalReactions,
            'is_reacted' => 1
        ]);
    }

    private function votePoll($user, $post, int $optionId)
    {
        // Validate that option belongs to this post's poll
        $pollId = (int)$post->poll_id;
        $option = PollOption::where('id', $optionId)->where('poll_id', $pollId)->first();
        if (!$option) {
            return response()->json([
                'status' => 422,
                'message' => 'Invalid poll option.'
            ], 422);
        }

        // Check if user already voted; if yes, update vote, else create
        $existing = PollVote::where('poll_id', $pollId)->where('user_id', $user->id)->first();
        if ($existing) {
            $existing->option_id = $optionId;
            $existing->save();
        } else {
            PollVote::create([
                'poll_id' => $pollId,
                'option_id' => $optionId,
                'user_id' => $user->id,
            ]);
        }

        // Recompute poll results
        $totalVotes = DB::table('poll_votes')->where('poll_id', $pollId)->count();
        $options = PollOption::where('poll_id', $pollId)->get();
        $results = $options->map(function ($opt) use ($totalVotes) {
            $votes = DB::table('poll_votes')->where('option_id', $opt->id)->count();
            $percentage = $totalVotes > 0 ? round(($votes / $totalVotes) * 100) : 0;
            return [
                'id' => $opt->id,
                'text' => $opt->option_text,
                'votes' => $votes,
                'percentage' => $percentage,
            ];
        });

        return response()->json([
            'status' => 200,
            'message' => 'Vote recorded successfully',
            'data' => [
                'total_votes' => $totalVotes,
                'options' => $results,
                'my_option_id' => $optionId,
            ],
        ]);
    }

    private function tipPostAuthor($tipper, $post, float $amount)
    {
        if ($amount <= 0) {
            return response()->json(['status' => 422, 'message' => 'Invalid amount'], 422);
        }
        if ($post->user_id === $tipper->id) {
            return response()->json(['status' => 400, 'message' => 'You cannot tip your own post'], 400);
        }

        DB::beginTransaction();
        try {
            $receiver = \App\Models\User::find($post->user_id);
            if (!$receiver) {
                return response()->json(['status' => 404, 'message' => 'Post author not found'], 404);
            }

            // Get or create wallets
            $tipperWallet = \App\Models\Wallet::firstOrCreate(['user_id' => $tipper->id], ['balance' => 0]);
            $receiverWallet = \App\Models\Wallet::firstOrCreate(['user_id' => $receiver->id], ['balance' => 0]);

            // Optional: ensure sufficient funds if tipping from wallet; here we allow negative? We'll enforce sufficient.
            if ($tipperWallet->balance < $amount) {
                return response()->json(['status' => 400, 'message' => 'Insufficient wallet balance'], 400);
            }

            // Deduct from tipper, credit receiver
            $tipperWallet->deductFunds($amount, 'Tip to post #' . $post->id, 'post_tip', $post->id, ['to' => $receiver->id]);
            $receiverWallet->addFunds($amount, 'Tip received for post #' . $post->id, 'post_tip', $post->id, ['from' => $tipper->id]);

            DB::commit();
            return response()->json(['status' => 200, 'message' => 'Tip sent successfully', 'data' => ['amount' => $amount]]);
        } catch (\Throwable $e) {
            DB::rollBack();
            return response()->json(['status' => 500, 'message' => 'Failed to send tip'], 500);
        }
    }


    public function getPostReactionsByType(Request $request)
    {
        // Validate request parameters
        $validatedData = $request->validate([
            'post_id' => 'required|integer|exists:posts,id',
            'reaction_type' => 'required|integer|in:1,2,3,4,5', // 1=Like, 2=Love, 3=Haha, 4=Wow, 5=Sad
            'offset' => 'nullable|integer|min:0',
            'limit' => 'nullable|integer|min:1|max:100', // Set max limit for performance
        ]);

        $postId = $validatedData['post_id'];
        $reactionType = $validatedData['reaction_type'];
        $offset = $validatedData['offset'] ?? 0;
        $limit = $validatedData['limit'] ?? 10;

        // Ensure the post exists
        $post = Post::find($postId);
        if (!$post) {
            return response()->json([
                'status' => 404,
                'message' => __('Api.post_not_found')
            ], 404);
        }

        try {
            // Fetch users who reacted with the specified type
            $users = DB::table('posts_reactions')
                ->join('users', 'posts_reactions.user_id', '=', 'users.id')
                ->where('posts_reactions.post_id', $postId)
                ->where('posts_reactions.reaction', $reactionType)
                ->orderBy('posts_reactions.created_at', 'desc')
                ->offset($offset)
                ->limit($limit)
                ->pluck('users.id'); // Get user IDs only

            // Get total count of this reaction type for the post
            $totalReactions = DB::table('posts_reactions')
                ->where('post_id', $postId)
                ->where('reaction', $reactionType)
                ->count();

            // Fetch user details using UserShortResource
            $userDetails = User::whereIn('id', $users)->get();

            return response()->json([
                'status' => 200,
                'message' => __('Api.reactions_fetched_successfully'),
                'reaction_type' => $reactionType,
                'total_reactions' => $totalReactions,
                'offset' => $offset,
                'limit' => $limit,
                'data' => UserShortResource::collection($userDetails) // Apply UserShortResource
            ], 200);
        } catch (\Exception $e) {
            // Log the error for debugging
            Log::error("Error fetching post reactions: " . $e->getMessage(), [
                'post_id' => $postId,
                'reaction_type' => $reactionType
            ]);

            return response()->json([
                'status' => 500,
                'message' => __('Api.error_occurred'),
                'error' => config('app.debug') ? $e->getMessage() : null
            ], 500);
        }
    }


    public function getPostActionsByType(Request $request)
    {
        // Validate input parameters
        $validatedData = $request->validate([
            'post_id' => 'required|integer|exists:posts,id',
            'action_type' => 'required|string|in:like,dislike,save,report,share', // Valid actions
            'offset' => 'nullable|integer|min:0',
            'limit' => 'nullable|integer|min:1|max:100', // Set max limit for performance
        ]);

        $postId = $validatedData['post_id'];
        $actionType = $validatedData['action_type'];
        $offset = $validatedData['offset'] ?? 0;
        $limit = $validatedData['limit'] ?? 10;

        // Ensure the post exists
        $post = Post::find($postId);
        if (!$post) {
            return response()->json([
                'status' => 404,
                'message' => __('Api.post_not_found')
            ], 404);
        }

        try {
            // Determine the correct table based on action type
            $tableMap = [
                'like' => 'post_likes',
                'dislike' => 'post_dislikes',
                'save' => 'posts_saved',
                'report' => 'posts_report',
                'share' => 'posts_shares' // Assuming you have a table for post shares
            ];

            $table = $tableMap[$actionType];

            // Fetch users who performed the specified action
            $users = DB::table($table)
                ->join('users', "{$table}.user_id", '=', 'users.id')
                ->where("{$table}.post_id", $postId)
                ->orderBy("{$table}.created_at", 'desc')
                ->offset($offset)
                ->limit($limit)
                ->pluck('users.id'); // Get user IDs only

            // Get total count of this action type for the post
            $totalActions = DB::table($table)
                ->where('post_id', $postId)
                ->count();

            // Fetch user details using UserShortResource
            $userDetails = User::whereIn('id', $users)->get();

            return response()->json([
                'status' => 200,
                'message' => __('Api.actions_fetched_successfully'),
                'action_type' => $actionType,
                'total_actions' => $totalActions,
                'offset' => $offset,
                'limit' => $limit,
                'data' => UserShortResource::collection($userDetails) // Apply UserShortResource
            ], 200);
        } catch (\Exception $e) {


            return response()->json([
                'status' => 500,
                'message' => __('Api.error_occurred'),
                'error' => config('app.debug') ? $e->getMessage() : null
            ], 500);
        }
    }


    public function changePostPrivacy(Request $request)
    {
        // Validate request parameters
        $validatedData = $request->validate([
            'post_id' => 'required|integer|exists:posts,id',
            'privacy_level' => 'required|integer|in:1,2,3,4', // 1=Public, 2=Friends-only, 3=Private, 4=Followers-only
        ]);

        $user = Auth::user();
        $postId = $validatedData['post_id'];
        $newPrivacyLevel = $validatedData['privacy_level'];

        // Fetch the post
        $post = Post::find($postId);
        if (!$post) {
            return response()->json([
                'status' => 404,
                'message' => __('Api.post_not_found')
            ], 404);
        }

        // Ensure the authenticated user is the post owner
        if ($post->user_id !== $user->id) {
            return response()->json([
                'status' => 403,
                'message' => __('Api.unauthorized_action')
            ], 403);
        }

        // Check if privacy is already set to the same level
        if ($post->privacy_level === $newPrivacyLevel) {
            return response()->json([
                'status' => 200,
                'message' => __('Api.privacy_already_set'),
                'privacy_level' => $post->privacy_level
            ]);
        }

        DB::beginTransaction();

        try {
            // Update privacy level
            $post->privacy_level = $newPrivacyLevel;
            $post->save();

            DB::commit();

            return response()->json([
                'status' => 200,
                'message' => __('Api.privacy_updated_successfully'),
                'privacy_level' => $post->privacy_level
            ]);
        } catch (\Exception $e) {
            DB::rollBack();

            // Log error for debugging
            // Log::error("Post Privacy Change Error: " . $e->getMessage(), [
            //     'user_id' => $user->id,
            //     'post_id' => $post->id,
            //     'new_privacy_level' => $newPrivacyLevel
            // ]);

            return response()->json([
                'status' => 500,
                'message' => __('Api.error_occurred'),
                'error' => config('app.debug') ? $e->getMessage() : null
            ], 500);
        }
    }

    public function postCommentAction(Request $request)
    {
        $validatedData = $request->validate([
            'post_id' => 'required|integer|exists:posts,id',
            'comment_id' => 'nullable|integer|exists:post_comments,id',
            'action' => 'required|string|in:add,edit,delete,like,reply,get,get-replies,like-reply,delete-reply',
            'content' => 'nullable|string|min:1|max:1000',
        ]);

        $user = Auth::user();
        $post = Post::find($validatedData['post_id']);

        if (!$post) {
            return response()->json([
                'status' => 404,
                'message' => __('Api.post_not_found')
            ], 404);
        }

        $action = $validatedData['action'];
        DB::beginTransaction();

        try {
            switch ($action) {
                case 'add':
                    return $this->addComment($user, $post, $validatedData['content']);

                case 'edit':
                    return $this->editComment($user, $validatedData['comment_id'], $validatedData['content']);

                case 'delete':
                    return $this->deleteComment($user, $validatedData['comment_id']);
                case 'like':
                    return $this->toggleCommentLike($user, $validatedData['comment_id']);

                case 'reply':
                    return $this->replyToComment($user, $post, $validatedData['comment_id'], $validatedData['content']);

                case 'get':
                    return $this->getComments($validatedData['post_id']);

                case 'get-replies':
                    return $this->getReplies($validatedData['comment_id']);

                case 'like-reply':
                    return $this->toggleReplyLike($user, $validatedData['comment_id']);

                case 'delete-reply':
                    return $this->deleteReply($user, $validatedData['comment_id']);

                default:
                    return response()->json([
                        'status' => 400,
                        'message' => __('Api.invalid_action')
                    ], 400);
            }
        } catch (\Exception $e) {
            DB::rollBack();

            return response()->json([
                'status' => 500,
                'message' => __('Api.error_occurred'),
                'error' => config('app.debug') ? $e->getMessage() : null
            ], 500);
        }
    }


    private function addComment($user, $post, $content)
    {
        if (empty($content)) {
            return response()->json([
                'status' => 422,
                'message' => __('Api.comment_content_required')
            ], 422);
        }

        $content = censor_text($content);

        $comment = PostComment::create([
            'post_id' => $post->id,
            'user_id' => $user->id,
            'content' => $content,
        ]);

        // Increment the comment count on the post
        $post->incrementComments();
        $userdata = User::select('device_id', 'notification_setting')
            ->where('id', $post->user_id)
            ->first(); // Make sure to use first() to get a single result

        if (!empty($userdata) && $user->id != $post->user_id) {
            // Decode the JSON column and access the 'notify_like' value
            $NotificationComment = json_decode(str_replace("\xc2\xa0", ' ', $userdata->notification_setting))->notify_comment;
            if ($NotificationComment == 1) {
                Notification::create([
                    'from_user_id' => $user->id,
                    'to_user_id' => $post->user_id,
                    'type' => 'post_comment',
                    'text' => 'commented on your post',
                    'post_id' => $post->id,
                ]);
                if (!empty($userdata->device_id)) {
                    sendFirebaseNotification($userdata->device_id, 'Commented on Post', $user->username . ' commented on your post');
                }
            }
        }

        DB::commit();

        // Process reward for creating a comment
        $this->rewardService->processReward(
            $user,
            'comment_create',
            $comment->id,
            ['post_id' => $post->id]
        );



        return response()->json([
            'status' => 200,
            'message' => __('Api.comment_added'),
            'data' => new CommentResource($comment->load('user', 'replies'))
        ]);
    }
    private function editComment($user, $commentId, $content)
    {
        if (empty($content)) {
            return response()->json([
                'status' => 422,
                'message' => __('Api.comment_content_required')
            ], 422);
        }

        $comment = PostComment::find($commentId);

        if (!$comment || $comment->user_id !== $user->id) {
            return response()->json([
                'status' => 403,
                'message' => __('Api.unauthorized_action')
            ], 403);
        }

        $comment->update([
            'content' => censor_text($content),
            'is_edited' => true,
        ]);

        DB::commit();


        return response()->json([
            'status' => 200,
            'message' => __('Api.comment_updated'),
            'data' => new CommentResource($comment->load('user', 'replies'))
        ]);
    }
    private function deleteComment($user, $commentId)
    {
        $comment = PostComment::find($commentId);

        if (!$comment || $comment->user_id !== $user->id) {
            return response()->json([
                'status' => 403,
                'message' => __('Api.unauthorized_action')
            ], 403);
        }

        $comment->delete();

        DB::commit();


        return response()->json([
            'status' => 200,
            'message' => __('Api.comment_deleted')
        ]);
    }
    private function toggleCommentLike($user, $commentId)
    {
        $comment = PostComment::find($commentId);

        if (!$comment) {
            return response()->json([
                'status' => 404,
                'message' => __('Api.comment_not_found')
            ], 404);
        }

        $existingLike = DB::table('comment_likes')
            ->where('comment_id', $comment->id)
            ->where('user_id', $user->id)
            ->first();

        if ($existingLike) {
            DB::table('comment_likes')->where('id', $existingLike->id)->delete();
            $comment->decrement('likes_count');

            DB::commit();


            return response()->json([
                'status' => 200,
                'message' => __('Api.comment_like_removed')
            ]);
        } else {
            DB::table('comment_likes')->insert([
                'comment_id' => $comment->id,
                'user_id' => $user->id,
                'created_at' => now()
            ]);
            $comment->increment('likes_count');

            DB::commit();

            return response()->json([
                'status' => 200,
                'message' => __('Api.comment_liked')
            ]);
        }
    }
    private function replyToComment($user, $post, $commentId, $content)
    {
        if (empty($content)) {
            return response()->json([
                'status' => 422,
                'message' => __('Api.comment_content_required')
            ], 422);
        }

        $parentComment = PostComment::find($commentId);

        if (!$parentComment) {
            return response()->json([
                'status' => 404,
                'message' => __('Api.comment_not_found')
            ], 404);
        }



        try {
            $reply = PostComment::create([
                'post_id'   => $post->id,
                'user_id'   => $user->id,
                'parent_id' => $parentComment->id,
                'content'   => censor_text($content)
            ]);

            // Reward should be part of the same transaction
            $this->rewardService->processReward(
                $user,
                'comment_reply',
                $reply->id,
                ['action' => 'reply']
            );
            DB::commit();

            $comments = PostComment::with(['user', 'replies.user'])->where('post_id', $post->id)->get();
            return response()->json([
                'status'  => 200,
                'message' => __('Api.comment_replied'),
                'data'    => CommentResource::collection($comments)
            ]);
        } catch (\Exception $e) {
            DB::rollBack();

            return response()->json([
                'status'  => 500,
                'message' => __('Api.error_occurred'),
                'error'   => config('app.debug') ? $e->getMessage() : null
            ], 500);
        }
    }




    private function getComments($postId)
    {
        $comments = PostComment::where('post_id', $postId)
            ->whereNull('parent_id')
            ->with(['user', 'replies.user']) // Load replies and reply user
            ->orderBy('created_at', 'desc')
            ->paginate(10);

        return response()->json([
            'status' => 200,
            'message' => __('Api.comments_fetched'),
            'data' => CommentResource::collection($comments)
        ], 200);
    }

    private function getReplies($commentId)
    {
        $replies = PostComment::where('parent_id', $commentId)
            ->with('user')
            ->orderBy('created_at', 'asc')
            ->paginate(10);

        return response()->json([
            'status' => 200,
            'message' => __('Api.replies_fetched'),
            'data' => CommentResource::collection($replies)
        ], 200);
    }

    private function toggleReplyLike($user, $commentId)
    {
        $reply = PostComment::find($commentId);

        if (!$reply) {
            return response()->json([
                'status' => 404,
                'message' => __('Api.comment_not_found')
            ], 404);
        }

        $existingLike = DB::table('comment_likes')
            ->where('comment_id', $reply->id)
            ->where('user_id', $user->id)
            ->first();

        if ($existingLike) {
            DB::table('comment_likes')->where('id', $existingLike->id)->delete();
            $reply->decrement('likes_count');

            DB::commit();

            return response()->json([
                'status' => 200,
                'message' => __('Api.comment_like_removed')
            ]);
        } else {
            DB::table('comment_likes')->insert([
                'comment_id' => $reply->id,
                'user_id' => $user->id,
                'created_at' => now()
            ]);
            $reply->increment('likes_count');

            DB::commit();

            // Process reward for adding a comment reply like
            $this->rewardService->processReward(
                $user,
                'comment_reply_like_add',
                $reply->id,
                ['action' => 'add']
            );

            return response()->json([
                'status' => 200,
                'message' => __('Api.comment_liked')
            ]);
        }
    }
    private function deleteReply($user, $commentId)
    {
        $reply = PostComment::find($commentId);

        if (!$reply || $reply->user_id !== $user->id) {
            return response()->json([
                'status' => 403,
                'message' => __('Api.unauthorized_action')
            ], 403);
        }

        $reply->delete();

        DB::commit();
        return response()->json([
            'status' => 200,
            'message' => __('Api.reply_deleted')
        ]);
    }
    public function trendingHashtags(Request $request)
    {
        $trendingHashtags = HashTag::select(['id', 'name'])->withCount('postTags')
            ->orderByDesc('post_tags_count')
            ->take(10) // Top 10, adjust as needed
            ->get();

        return response()->json([
            'status' => 200,
            'message' => __('Api.trending_hashtags_fetch_success'),
            'data' => []
        ]);
    }
    public function votePollOption(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'poll_id' => 'required|integer',
            'poll_option_id' => 'required|integer',
        ], [
            'poll_id.required' => __('api.poll_id_required'),
            'poll_id.integer' => __('api.poll_id_integer'),
            'poll_option_id.required' => __('api.poll_option_id_required'),
            'poll_option_id.integer' => __('api.poll_option_id_integer'),
        ]);

        if ($validator->fails()) {
            return response()->json([
                'status' => 400,
                'message' => $validator->errors()->first(),
            ], 200);
        }

        $user = Auth::user();
        $pollId = $request->poll_id;
        $pollOptionId = $request->poll_option_id;

        $poll = Poll::find($pollId);
        if (!$poll) {
            return response()->json([
                'status' => 400,
                'message' => __('api.poll_not_found'),
            ]);
        }

        // ✅ Check poll option exists
        $pollOption = PollOption::find($pollOptionId);
        if (!$pollOption) {
            return response()->json([
                'status' => 400,
                'message' => __('api.poll_option_not_found'),
            ]);
        }

        // ✅ Check if user already voted
        $alreadyVoted = PollVote::where('user_id', $user->id)
            ->where('poll_id', $pollId)
            ->first();

        if ($alreadyVoted) {
            return response()->json([
                'status' => 400,
                'message' => __('api.already_voted'),
            ]);
        }

        // ✅ Save vote
        PollVote::create([
            'user_id' => $user->id,
            'poll_id' => $pollId,
            'option_id' => $pollOptionId,
        ]);

        return response()->json([
            'status' => 200,
            'message' => __('api.vote_successful'),
        ]);
    }
}
