<?php


namespace App\Http\Controllers;

use Carbon\Carbon;
use App\Models\User;
use App\Models\Friend;
use App\Models\Follower;
use App\Models\Notification;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Http\Resources\UserShortResource;
use Illuminate\Support\Facades\Validator;

class FriendController extends Controller
{


    /**
     * Get user's friends list.
     */


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

    //      // Fetch friends, including their relationships
    //      $friends = Friend::getUserFriends($user->id);

    //      // Transform each friend to a UserShortResource
    //      $friendsTransformed = $friends->map(function ($friend) use ($user) {
    //          // Determine which user is the "friend" (not the currently authenticated user)
    //          $friendUser = $friend->friend_one === $user->id ? $friend->friendTwo : $friend->friendOne;

    //          // Apply the resource to return the appropriate data structure
    //          return new UserShortResource($friendUser);
    //      });

    //      return response()->json([
    //          'status' => 200,
    //          'message' => 'Success',
    //          'data' => $friendsTransformed
    //      ], 200);
    //  }

    public function getFriends(Request $request)
    {
        $user = Auth::user();
        $keyword = $request->input('keyword');
        $limit = $request->input('limit', 12); // Default 12 friends per page
        $offset = $request->input('offset', 0); // Default offset 0

        // Build the base query
        $query = Friend::where(function ($query) use ($user) {
            $query->where('friend_one', $user->id)
                ->orWhere('friend_two', $user->id);
        })
            ->where('status', 1); // ✅ Only accepted friends

        // Apply keyword search if provided
        if ($keyword) {
            $query->where(function ($query) use ($keyword) {
                $query->whereHas('friendOne', function ($q) use ($keyword) {
                    $q->where('name', 'like', '%' . $keyword . '%')
                        ->orWhere('username', 'like', '%' . $keyword . '%');
                })
                    ->orWhereHas('friendTwo', function ($q) use ($keyword) {
                        $q->where('name', 'like', '%' . $keyword . '%')
                            ->orWhere('username', 'like', '%' . $keyword . '%');
                    });
            });
        }

        // Get total count before pagination
        $totalCount = $query->count();

        // Apply pagination
        $friends = $query->skip($offset)
            ->take($limit)
            ->get();

        // Transform to resource
        $friendsTransformed = $friends->map(function ($friend) use ($user) {
            $friendUser = $friend->friend_one === $user->id ? $friend->friendTwo : $friend->friendOne;
            return new UserShortResource($friendUser);
        });

        return response()->json([
            'status' => 200,
            'message' => 'Friends fetched successfully',
            'data' => $friendsTransformed,
            'pagination' => [
                'total' => $totalCount,
                'limit' => $limit,
                'offset' => $offset,
                'has_more' => ($offset + $limit) < $totalCount
            ]
        ], 200);
    }




    public function getSentFriendRequests(Request $request)
    {
        $userId = Auth::id();
        $sentRequests = Friend::with('friendTwo')
            ->where('friend_one', $userId)
            ->where('status', 0) // Assuming '0' is the status for pending friend requests
            ->get();

        $sentRequestsTransformed = $sentRequests->map(function ($request) {
            return [
                'id' => $request->id,
                'to_user' => new UserShortResource($request->friendTwo),
                'sent_at' => $request->created_at,
            ];
        });

        return response()->json([
            'status' => 200,
            'message' => 'Sent friend requests fetched successfully',
            'data' => $sentRequestsTransformed,
        ], 200);
    }


    // Accept/Decline Friend Request
    public function friendRequestAction(Request $request)
    {
        // Validation
        $validator = Validator::make($request->all(), [
            'user_id' => 'required|exists:users,id',
            'request_action' => 'required|in:accept,decline',
        ]);

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

        // Business Logic
        $userId = $request->user_id;
        $action = $request->request_action;
        $currentUser = Auth::user();

        $friendRequest = Friend::where(['friend_one' => $userId, 'friend_two' => $currentUser->id, 'status' => 0])->first();

        if (!$friendRequest) {
            return response()->json(['status' => 404, 'message' => 'Friend request not found'], 200);
        }

        if ($action === 'accept') {
            $friendRequest->update(['status' => 1, 'accepted_time' => now()]);

            $userdata = User::select('device_id', 'notification_setting')
                ->where('id', $userId)
                ->first(); // Make sure to use first() to get a single result

            if ($userdata && $userId != $currentUser->id) {
                // Decode the JSON column and access the 'notify_like' value
                $notifyAcceptRequest = json_decode(str_replace("\xc2\xa0", ' ', $userdata->notification_setting))->notify_accept_request;
                if ($notifyAcceptRequest == 1) {
                    Notification::create([
                        'from_user_id' => $currentUser->id,
                        'to_user_id' => $userId,
                        'type' => 'accepted_request',
                        'text' => 'Accepted your friend request.',
                    ]);
                    if (!empty($userdata->device_id)) {
                        sendFirebaseNotification($userdata->device_id, 'Friend request Accepted', $currentUser->username . ' accepted your friend request');
                    }
                }
            }


            return response()->json(['status' => 200, 'message' => 'Friend request accepted']);
        } elseif ($action === 'decline') {
            $friendRequest->delete();
            return response()->json(['status' => 200, 'message' => 'Friend request declined']);
        }
    }

    // Send Friend Request
    public function sendFriendRequest(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'friend_two' => 'required|exists:users,id',
        ]);

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

        $friendTwo = $request->friend_two;
        $loggedinUser = Auth::user();
        $friendOne = $loggedinUser->id;

        // Check existing request
        $existingRequest = Friend::where(function ($query) use ($friendOne, $friendTwo) {
            $query->where('friend_one', $friendOne)->where('friend_two', $friendTwo);
        })->orWhere(function ($query) use ($friendOne, $friendTwo) {
            $query->where('friend_two', $friendOne)->where('friend_one', $friendTwo);
        })->first();

        if ($existingRequest) {
            return response()->json(['status' => 200, 'message' => 'Friend request already exists']);
        }

        // Create request
        Friend::create(['friend_one' => $friendOne, 'friend_two' => $friendTwo, 'status' => 0]);

        $userdata = User::select('device_id', 'notification_setting')
            ->where('id', $friendTwo)
            ->first(); // Make sure to use first() to get a single result

        if ($userdata && $friendOne != $friendTwo) {
            // Decode the JSON column and access the 'notify_like' value
            $notifySentRequest = json_decode(str_replace("\xc2\xa0", ' ', $userdata->notification_setting))->notify_send_request;
            if ($notifySentRequest == 1) {
                Notification::create([
                    'from_user_id' => $friendOne,
                    'to_user_id' => $friendTwo,
                    'type' => 'sent_request',
                    'text' => 'Sent you a friend request.',
                ]);
                if (!empty($userdata->device_id)) {
                    sendFirebaseNotification($userdata->device_id, 'Friend request ', $loggedinUser->username . ' sent you friend request');
                }
            }
        }
        return response()->json(['status' => 200, 'message' => 'Friend request sent']);
    }

    public function unfriend(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'user_id' => 'required|exists:users,id',
        ]);

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

        $userId = $request->user_id;
        $currentUserId = Auth::id();

        $friendship = Friend::where(function ($query) use ($currentUserId, $userId) {
            $query->where('friend_one', $currentUserId)->where('friend_two', $userId);
        })->orWhere(function ($query) use ($currentUserId, $userId) {
            $query->where('friend_two', $currentUserId)->where('friend_one', $userId);
        })->first();

        if (!$friendship) {
            return response()->json(['status' => 404, 'message' => 'Friendship not found'], 200);
        }

        $friendship->delete();

        // Optionally delete related follower data
        Follower::where(function ($query) use ($currentUserId, $userId) {
            $query->where('follower_id', $currentUserId)->where('following_id', $userId);
        })->orWhere(function ($query) use ($currentUserId, $userId) {
            $query->where('follower_id', $userId)->where('following_id', $currentUserId);
        })->delete();

        return response()->json(['status' => 200, 'message' => 'Successfully unfriended']);
    }

    public function fetchRecommended(Request $request)
    {
        $loggedInUserId = Auth::id();
        $keyword = $request->input('keyword', null);
        $gender = $request->input('gender', null);
        $relation = $request->input('relation', null);
        $offset = $request->offset ?? 0;
        $limit = $request->limit ?? 10;

        $recommendedUsers = User::select(userShortModelDefination())
            ->whereNotIn('id', function ($query) use ($loggedInUserId) {
                $query->select('friend_two')
                    ->from('friends')
                    ->where('friend_one', $loggedInUserId);
            })
            ->whereNotIn('id', function ($query) use ($loggedInUserId) {
                $query->select('friend_one')
                    ->from('friends')
                    ->where('friend_two', $loggedInUserId);
            })
            ->where('id', '!=', $loggedInUserId)
            ->when(!empty($keyword), function ($query) use ($keyword) {
                $query->where(function ($q) use ($keyword) {
                    $q->where('first_name', 'LIKE', "%$keyword%")
                        ->orWhere('last_name', 'LIKE', "%$keyword%");
                });
            })
            ->when(!empty($gender), function ($query) use ($gender) {
                $query->where('gender', $gender);
            })
            ->when(!empty($relation), function ($query) use ($relation) {
                $query->where('relation', $relation);
            })
            ->offset($offset)
            ->limit($limit)
            ->get();
        $modifiedUsers = $recommendedUsers->map(function ($user) use ($loggedInUserId) {
            $user->mutual_friends_count = Friend::where('friend_one', $loggedInUserId)
                ->whereIn('friend_two', function ($query) use ($user) {
                    $query->select('friend_two')
                        ->from('friends')
                        ->where('friend_one', $user->id);
                })
                ->count();
            return $user;
        });

        return response()->json([
            'status' => 200,
            'message' => $modifiedUsers->isEmpty() ? 'No recommendations found' : 'Recommendations found',
            'data' => UserShortResource::collection($modifiedUsers),
        ]);
    }

    public function getReceivedFriendRequests(Request $request)
    {
        $userId = Auth::id();
        $receivedRequests = Friend::with('friendOne')
            ->where('friend_two', $userId)
            ->where('status', 0) // Assuming '0' indicates pending requests
            ->get();

        $receivedRequestsTransformed = $receivedRequests->map(function ($request) {
            return [
                'id' => $request->id,
                'from_user' => new UserShortResource($request->friendOne),
                'received_at' => $request->created_at,
            ];
        });

        return response()->json([
            'status' => 200,
            'message' => 'Received friend requests fetched successfully',
            'data' => $receivedRequestsTransformed,
        ], 200);
    }


    public function changeFriendRole(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'user_id' => 'required|exists:users,id',
            'role' => 'required|in:2,3,4', // 2: Friend, 3: Family, 4: Business
        ]);

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

        $userId = $request->user_id;
        $role = $request->role;
        $currentUserId = Auth::id();

        $friendship = Friend::where(function ($query) use ($currentUserId, $userId) {
            $query->where('friend_one', $currentUserId)->where('friend_two', $userId);
        })->orWhere(function ($query) use ($currentUserId, $userId) {
            $query->where('friend_two', $currentUserId)->where('friend_one', $userId);
        })->first();

        if (!$friendship) {
            return response()->json(['status' => 404, 'message' => 'Friendship not found'], 200);
        }

        $friendship->update(['role' => $role]);

        $roles = [
            '2' => 'Friend',
            '3' => 'Family',
            '4' => 'Business',
        ];

        return response()->json([
            'status' => 200,
            'message' => sprintf('Friend role updated to %s', $roles[$role]),
        ]);
    }

    /**
     * Get user's followers.
     */
    public function getFollowers(Request $request)
    {
        $user = Auth::user();
        $followers = Follower::where('following_id', $user->id)->get();

        return response()->json(['status' => 200, 'message' => 'Success', 'data' => $followers], 200);
    }


    public function getStats()
    {
        $userId = Auth::id();
        if (!$userId) {
            return response()->json([
                'status' => 401,
                'message' => 'Unauthenticated',
            ], 200);
        }


        // Count total friends
        $totalFriends = Friend::where(function ($query) use ($userId) {
            $query->where('friend_one', $userId)->orWhere('friend_two', $userId);
        })->where('status', 1) // Ensure they are accepted friends
            ->count();

        // Count online friends (assuming 'last_seen' column exists in users table)
        $onlineFriends = User::whereIn('id', Friend::where(function ($query) use ($userId) {
            $query->where('friend_one', $userId)->orWhere('friend_two', $userId);
        })->where('status', 1)->pluck('friend_one'))
            ->where('last_seen', '>=', Carbon::now()->subMinutes(5))
            ->count();

        // Count birthdays today
        $birthdaysToday = User::whereIn('id', Friend::where(function ($query) use ($userId) {
            $query->where('friend_one', $userId)->orWhere('friend_two', $userId);
        })->where('status', 1)->pluck('friend_one'))
            ->whereMonth('date_of_birth', Carbon::now()->month)
            ->whereDay('date_of_birth', Carbon::now()->day)
            ->count();

        // Count new friend requests
        $newRequests = Friend::where('friend_two', $userId)->where('status', 0)->count();

        return response()->json([
            'status' => 200,
            'message' => 'Stats fetched successfully',
            'data' => [
                'total_friends' => $totalFriends,
                'online_now' => $onlineFriends,
                'birthdays_today' => $birthdaysToday,
                'new_requests' => $newRequests
            ]
        ]);
    }

    /**
     * Get suggested users for "Who to Follow" section
     */
    public function getSuggestedUsers(Request $request)
    {
        $user = Auth::user();

        if (!$user) {
            return response()->json([
                'status' => 401,
                'message' => 'Unauthenticated',
            ], 401);
        }

        $limit = $request->input('limit', 3); // Default to 3 suggestions

        // Get users that are not already friends and not the current user
        $friendIds = Friend::where(function ($query) use ($user) {
            $query->where('friend_one', $user->id)
                ->orWhere('friend_two', $user->id);
        })->where('status', 1)->get()
            ->map(function ($friend) use ($user) {
                return $friend->friend_one === $user->id ? $friend->friend_two : $friend->friend_one;
            })->toArray();

        // Get users that have pending friend requests
        $pendingRequestIds = Friend::where(function ($query) use ($user) {
            $query->where('friend_one', $user->id)
                ->orWhere('friend_two', $user->id);
        })->where('status', 0)->get()
            ->map(function ($friend) use ($user) {
                return $friend->friend_one === $user->id ? $friend->friend_two : $friend->friend_one;
            })->toArray();

        // Exclude friends, pending requests, and current user
        $excludeIds = array_merge($friendIds, $pendingRequestIds, [$user->id]);

        // Get random users to suggest
        $suggestedUsers = User::whereNotIn('id', $excludeIds)
            ->inRandomOrder()
            ->limit($limit)
            ->get();

        // Transform to UserShortResource
        $suggestions = $suggestedUsers->map(function ($suggestedUser) {
            return new UserShortResource($suggestedUser);
        });

        return response()->json([
            'status' => 200,
            'message' => 'Suggested users fetched successfully',
            'data' => $suggestions
        ]);
    }
}
