<?php

namespace App\Http\Controllers;

use App\Models\User;
use App\Models\Group;

use App\Models\GroupMember;
use Illuminate\Support\Str;
use App\Models\Notification;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use App\Http\Resources\GroupResource;
use App\Http\Resources\UserShortResource;
use Illuminate\Support\Facades\Validator;

class GroupController extends Controller
{
    /**
     * Fetch all groups.
     */
    public function getAllGroups(Request $request)
    {
        $userId = Auth::id();
        $limit = (int) $request->input('limit', 6);
        $sort = $request->input('sort', 'newest');
        $search = $request->input('search', '');
        $isMe = $request->boolean('isMe', false);
        $following = $request->boolean('following', false);
        $privacy = $request->input('privacy', '');
        $memberCount = $request->input('member_count', '');
        $activityLevel = $request->input('activity_level', '');
        $location = $request->input('location', '');
        $categories = $request->input('categories', '');
        $verified = $request->boolean('verified', false);
        $unverified = $request->boolean('unverified', false);

        $query = Group::withCount('members')
            ->addSelect([
                'is_group_owner' => DB::raw("CASE WHEN user_id = $userId THEN 1 ELSE 0 END AS is_group_owner"),
                'already_member' => DB::raw("EXISTS (SELECT 1 FROM group_members WHERE group_id = groups.id AND user_id = $userId) AS already_member")
            ]);

        // Show only user's groups if isMe is true
        if ($isMe) {
            $query->where('user_id', $userId);
        }

        // Show only groups user has joined if following is true
        if ($following) {
            $query->whereHas('members', function ($q) use ($userId) {
                $q->where('user_id', $userId);
            });
        }

        // Apply search if provided
        if (!empty($search)) {
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                    ->orWhere('description', 'like', "%{$search}%");
            });
        }

        // Apply privacy filter
        if (!empty($privacy)) {
            $query->where('privacy', $privacy);
        }

        // Apply member count filter
        if (!empty($memberCount)) {
            switch ($memberCount) {
                case 'small':
                    $query->having('members_count', '<', 100);
                    break;
                case 'medium':
                    $query->having('members_count', '>=', 100)->having('members_count', '<=', 1000);
                    break;
                case 'large':
                    $query->having('members_count', '>', 1000);
                    break;
            }
        }

        // Apply activity level filter (placeholder - would need activity tracking)
        if (!empty($activityLevel)) {
            // This would need to be implemented based on actual activity tracking
            // For now, we'll use a placeholder
        }

        // Apply location filter (placeholder - would need location data)
        if (!empty($location)) {
            // This would need to be implemented based on actual location data
        }

        // Apply category filter
        if (!empty($categories)) {
            $categoryArray = is_array($categories) ? $categories : explode(',', $categories);
            $query->whereIn('category_id', $categoryArray);
        }

        // Apply verification filter (placeholder - would need verification system)
        if ($verified) {
            // This would need to be implemented based on actual verification system
        }

        if ($unverified) {
            // This would need to be implemented based on actual verification system
        }

        // Apply sorting
        switch ($sort) {
            case 'alphabetical':
                $query->orderBy('name', 'asc');
                break;
            case 'most_members':
                $query->orderBy('members_count', 'desc');
                break;
            case 'least_members':
                $query->orderBy('members_count', 'asc');
                break;
            case 'oldest':
                $query->orderBy('created_at', 'asc');
                break;
            case 'newest':
            default:
                $query->orderBy('created_at', 'desc');
                break;
        }

        $groups = $query->paginate($limit);

        if ($groups->isEmpty()) {
            return response()->json([
                'status' => 200,
                'message' => __('Api.no_groups_found'),
                'data' => [],
            ], 200);
        }

        return response()->json([
            'status' => 200,
            'message' => __('Api.data_fetched'),
            'data' => GroupResource::collection($groups),
            'pagination' => [
                'total' => $groups->total(),
                'per_page' => $groups->perPage(),
                'current_page' => $groups->currentPage(),
                'last_page' => $groups->lastPage(),
                'total_pages' => $groups->lastPage(),
                'from' => $groups->firstItem(),
                'to' => $groups->lastItem()
            ]
        ], 200);
    }

    /**
     * Fetch groups the user has joined.
     */
    public function getUserGroups()
    {
        $userId = Auth::id();
        $groups = Group::where('user_id', $userId)->get();

        if ($groups->isEmpty()) {
            return response()->json([
                'status' => 200,
                'message' => __('Api.no_user_groups_found'),
                'data' => [],
            ], 200);
        }

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

    /**
     * Create a new group.
     */
    public function createGroup(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|min:3|max:50',
            'description' => 'required|string|min:10|max:500',
            'privacy' => 'required|string|in:public,private,hidden',
            'cover_image' => 'required|image|mimes:jpeg,png,jpg|max:2048'
        ]);

        if ($validator->fails()) {
            return response()->json([
                'status' => 422,
                'message' => __('Api.validation_failed'),
                'errors' => $validator->errors(),
            ], 200);
        }

        $groupData = $validator->validated();
        $groupData['user_id'] = Auth::id();
        $groupData['privacy'] = $request->privacy;
        $groupData['slug'] = Str::slug($request->name);

        // Check if slug exists
        $existingGroup = Group::where('slug', $groupData['slug'])->first();
        if ($existingGroup) {
            return response()->json([
                'status' => 422,
                'message' => __('Api.validation_failed'),
                'errors' => ['name' => ['A group with this URL already exists']],
            ], 200);
        }

        $groupData['is_private'] = $request->privacy === 'private' ? true : false;
        $groupData['allow_members_to_post'] = $request->privacy === 'public' ? true : false;

        // Handle cover image upload
        if ($request->hasFile('cover_image')) {
            $groupData['cover_image'] = storeMedia($request->file('cover_image'), 'group_covers');
        }
        // Create group with all required fields including slug

        $group = Group::create($groupData);

        // Add creator as admin member
        GroupMember::create([
            'group_id' => $group->id,
            'user_id' => Auth::id(),
            'role' => 'admin'
        ]);

        return response()->json([
            'status' => 200,
            'message' => __('Api.group_created_successfully'),
            'data' => new GroupResource($group),
        ], 200);
    }

    /**
     * Update group details.
     */
    public function updateGroup(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'group_id' => 'required|exists:groups,id',
            'name' => 'nullable|string|min:3|max:50',
            'description' => 'nullable|string|min:10|max:500',
            'privacy' => 'nullable|string|in:public,private',
            'cover_image' => 'nullable|string|url',
            'is_private' => 'nullable|boolean',
            'allow_members_to_post' => 'nullable|boolean',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'status' => 422,
                'message' => __('Api.validation_failed'),
                'errors' => $validator->errors(),
            ], 200);
        }

        $group = Group::find($request->group_id);

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

        $group->update(array_filter($validator->validated()));

        return response()->json([
            'status' => 200,
            'message' => __('Api.group_updated_successfully'),
            'data' => new GroupResource($group),
        ], 200);
    }

    /**
     * Delete a group.
     */
    public function deleteGroup(Request $request)
    {
        $request->validate(['group_id' => 'required|exists:groups,id']);
        $group = Group::find($request->group_id);

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

        $group->delete();

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

    /**
     * Join a group.
     */
    public function joinGroup(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'group_id' => 'required|exists:groups,id',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'status' => 422,
                'message' => __('Api.validation_failed'),
                'errors' => $validator->errors(),
            ], 200);
        }

        $loggedinUser = Auth::user();
        $userId = $loggedinUser->id;
        $groupId = $request->group_id;
        $group = Group::find($groupId);
        if (empty($group)) {
            return response()->json([
                'status' => 400,
                'message' => __('Api.group_not_found'),
            ], 200);
        }
        if (GroupMember::where(['group_id' => $groupId, 'user_id' => $userId])->exists()) {
            return response()->json([
                'status' => 400,
                'message' => __('Api.already_a_member'),
            ], 200);
        }

        GroupMember::create(['group_id' => $groupId, 'user_id' => $userId, 'role' => 'member']);
        Group::where('id', $groupId)->increment('members_count');
        $userdata = User::select('device_id', 'notification_setting')
            ->where('id', $group->user_id)
            ->first(); // Make sure to use first() to get a single result

        if (!empty($userdata) && $userId != $group->user_id) {
            // Decode the JSON column and access the 'notify_like' value
            $notifyJoinedGroup = json_decode(str_replace("\xc2\xa0", ' ', $userdata->notification_setting))->notify_joined_group;
            if ($notifyJoinedGroup == 1) {
                Notification::create([
                    'from_user_id' => $userId,
                    'to_user_id' => $group->user_id,
                    'type' => 'join_group',
                    'text' => 'joined your group',
                    'group_id' => $group->id,
                ]);
                if (!empty($userdata->device_id)) {
                    sendFirebaseNotification($userdata->device_id, 'Group joined ', $loggedinUser->username . ' joined your group');
                }
            }
        }

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

    /**
     * Join or leave a group (toggle functionality)
     */
    public function joinLeaveGroup(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'group_id' => 'required|exists:groups,id',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'status' => 422,
                'message' => __('Api.validation_failed'),
                'errors' => $validator->errors(),
            ], 200);
        }

        $userId = Auth::id();
        $groupId = $request->group_id;
        $group = Group::find($groupId);

        if (empty($group)) {
            return response()->json([
                'status' => 400,
                'message' => __('Api.group_not_found'),
            ], 200);
        }

        $member = GroupMember::where(['group_id' => $groupId, 'user_id' => $userId])->first();

        if ($member) {
            // User is already a member, so leave the group
            $member->delete();
            Group::where('id', $groupId)->decrement('members_count');

            return response()->json([
                'status' => 200,
                'message' => 'Left group successfully',
                'action' => 'left',
                'members_count' => $group->members_count - 1
            ], 200);
        } else {
            // User is not a member, so join the group
            GroupMember::create(['group_id' => $groupId, 'user_id' => $userId, 'role' => 'member']);
            Group::where('id', $groupId)->increment('members_count');

            Notification::create([
                'from_user_id' => $userId,
                'to_user_id' => $group->user_id,
                'type' => 'join_group',
                'text' => 'joined your group',
                'group_id' => $group->id,
            ]);

            return response()->json([
                'status' => 200,
                'message' => 'Joined group successfully',
                'action' => 'joined',
                'members_count' => $group->members_count + 1
            ], 200);
        }
    }

    /**
     * Leave a group.
     */
    public function leaveGroup(Request $request)
    {
        $request->validate(['group_id' => 'required|exists:groups,id']);
        $userId = Auth::id();
        $groupId = $request->group_id;

        $member = GroupMember::where(['group_id' => $groupId, 'user_id' => $userId])->first();

        if (!$member) {
            return response()->json([
                'status' => 400,
                'message' => __('Api.not_a_member'),
            ], 200);
        }

        $member->delete();
        Group::where('id', $groupId)->decrement('members_count');

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

    /**
     * Fetch group members.
     */
    public function getGroupMembers($groupId)
    {
        $members = GroupMember::where('group_id', $groupId)->with('user')->get();

        if ($members->isEmpty()) {
            return response()->json([
                'status' => 400,
                'message' => __('Api.no_members_found'),
                'data' => [],
            ], 200);
        }
        $data = $members->map(function ($member) {
            // Use the UserShortResource to return the user details
            $userData = new UserShortResource($member->user);

            // Add the role to the user data
            $userData = $userData->toArray(null);  // Convert resource to array
            $userData['role'] = $member->role;  // Add role dynamically

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

    /**
     * Make a user admin.
     */
    public function makeAdmin(Request $request)
    {
        $request->validate([
            'group_id' => 'required|exists:groups,id',
            'user_id' => 'required|exists:users,id'
        ]);

        GroupMember::where(['group_id' => $request->group_id, 'user_id' => $request->user_id])->update(['role' => 'admin']);

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

    /**
     * Remove admin privileges.
     */
    public function removeAdmin(Request $request)
    {
        $request->validate([
            'group_id' => 'required|exists:groups,id',
            'user_id' => 'required|exists:users,id'
        ]);

        GroupMember::where(['group_id' => $request->group_id, 'user_id' => $request->user_id])->update(['role' => 'member']);

        return response()->json([
            'status' => 200,
            'message' => __('Api.admin_privileges_removed'),
        ], 200);
    }
    public function removeMember(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'group_id' => 'required|exists:groups,id',
            'user_id' => 'required|exists:users,id',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'status' => 422,
                'message' => __('Api.validation_failed'),
                'errors' => $validator->errors(),
            ], 200);
        }

        $group = Group::find($request->group_id);
        $admin = GroupMember::where('group_id', $request->group_id)
            ->where('user_id', Auth::id())
            ->where('role', 'admin')
            ->first();

        if (!$admin) {
            return response()->json([
                'status' => 403,
                'message' => __('Api.unauthorized_action'),
            ], 200);
        }

        $member = GroupMember::where('group_id', $request->group_id)
            ->where('user_id', $request->user_id)
            ->first();

        if (!$member) {
            return response()->json([
                'status' => 200,
                'message' => __('Api.member_not_found'),
            ], 200);
        }

        if ($member->role === 'admin') {
            return response()->json([
                'status' => 403,
                'message' => __('Api.cannot_remove_admin'),
            ], 200);
        }

        $member->delete();
        Group::where('id', $request->group_id)->decrement('members_count');

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

    /**
     * Fetch groups that the authenticated user has joined.
     */
    public function getJoinedGroups(Request $request)
    {
        $userId = Auth::id();

        // Fetch groups where the user is a member
        $groups = Group::whereHas('members', function ($query) use ($userId) {
            $query->where('user_id', $userId);
        })
            ->where('user_id', '!=', $userId)
            ->get();

        if ($groups->isEmpty()) {
            return response()->json([
                'status' => 200,
                'message' => __('Api.no_groups_found'),
                'data' => []
            ], 200);
        }

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

    /**
     * Fetch group details by group ID.
     */
    public function getGroupDetail($groupId)
    {
        // Fetch the group by ID
        $group = Group::withCount('members')->find($groupId);

        if (!$group) {
            return response()->json([
                'status' => 200,
                'message' => __('Api.group_not_found'),
                'data' => null,
            ], 200);
        }

        return response()->json([
            'status' => 200,
            'message' => __('Api.group_fetched_successfully'),
            'data' => new GroupResource($group),
        ], 200);
    }

    /**
     * Get suggested groups for the authenticated user
     */
    public function getSuggestedGroups()
    {
        try {
            $userId = Auth::id();

            // Get groups that the user hasn't joined yet
            $suggestedGroups = Group::whereNotIn('id', function ($query) use ($userId) {
                $query->select('group_id')
                    ->from('group_members')
                    ->where('user_id', $userId);
            })
                ->where('user_id', '!=', $userId) // Exclude user's own groups
                ->with('category')
                ->withCount('members')
                ->orderBy('members_count', 'desc')
                ->limit(5)
                ->get();

            return response()->json([
                'success' => true,
                'groups' => $suggestedGroups->map(function ($group) {
                    $name = $group->name ?? $group->group_name ?? 'Untitled Group';
                    $coverImage = $group->cover_image ?? $group->group_cover_image ?? null;
                    $membersCount = $group->members_count ?? $group->members()->count();
                    $categoryName = optional($group->category)->name ?? $group->group_category ?? null;

                    return [
                        'id' => $group->id,
                        'name' => $name,
                        'cover_image' => $coverImage ? getMedia($coverImage, 'cover') : null,
                        'members_count' => $membersCount,
                        'category' => $categoryName,
                        'slug' => $group->slug ?? null,
                    ];
                })
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to load suggested groups'
            ], 500);
        }
    }

    /**
     * Invite users to a group
     */
    public function inviteUsers(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'group_id' => 'required|exists:groups,id',
            'user_ids' => 'required|array',
            'user_ids.*' => 'required|exists:users,id',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'status' => 422,
                'message' => __('Api.validation_failed'),
                'errors' => $validator->errors(),
            ], 200);
        }

        $groupId = $request->group_id;
        $userIds = $request->user_ids;
        $sender = Auth::user();
        $group = Group::find($groupId);

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

        // Check if user is a member or owner
        $isMember = GroupMember::where('group_id', $groupId)
            ->where('user_id', Auth::id())
            ->exists();
        
        if (!$isMember && $group->user_id !== Auth::id()) {
            return response()->json([
                'status' => 403,
                'message' => __('Api.unauthorized_action'),
            ], 200);
        }

        $invitedCount = 0;
        $alreadyInvited = [];
        $alreadyMembers = [];

        foreach ($userIds as $userId) {
            // Skip if user is already a member
            if (GroupMember::where('group_id', $groupId)->where('user_id', $userId)->exists()) {
                $alreadyMembers[] = $userId;
                continue;
            }

            // Check if already invited (notification exists)
            $existingInvite = \App\Models\Notification::where('from_user_id', Auth::id())
                ->where('to_user_id', $userId)
                ->where('group_id', $groupId)
                ->where('type', 'group_invite')
                ->where('seen', false)
                ->exists();

            if ($existingInvite) {
                $alreadyInvited[] = $userId;
                continue;
            }

            // Send invite notification
            \App\Services\NotificationService::sendGroupInvite($sender, \App\Models\User::find($userId), $group);
            $invitedCount++;
        }

        return response()->json([
            'status' => 200,
            'message' => __('Api.invites_sent_successfully'),
            'data' => [
                'invited_count' => $invitedCount,
                'already_invited' => count($alreadyInvited),
                'already_members' => count($alreadyMembers),
            ],
        ], 200);
    }

    /**
     * Add users directly to a group (owner only)
     */
    public function addMembers(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'group_id' => 'required|exists:groups,id',
            'user_ids' => 'required|array',
            'user_ids.*' => 'required|exists:users,id',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'status' => 422,
                'message' => __('Api.validation_failed'),
                'errors' => $validator->errors(),
            ], 200);
        }

        $groupId = $request->group_id;
        $userIds = $request->user_ids;
        $group = Group::find($groupId);

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

        // Only group owner can add members directly
        if ($group->user_id !== Auth::id()) {
            return response()->json([
                'status' => 403,
                'message' => __('Api.unauthorized_action'),
            ], 200);
        }

        $addedCount = 0;
        $alreadyMembers = [];

        foreach ($userIds as $userId) {
            // Skip if user is already a member
            if (GroupMember::where('group_id', $groupId)->where('user_id', $userId)->exists()) {
                $alreadyMembers[] = $userId;
                continue;
            }

            // Add user as member
            GroupMember::create([
                'group_id' => $groupId,
                'user_id' => $userId,
                'role' => 'member'
            ]);

            // Increment members count
            Group::where('id', $groupId)->increment('members_count');

            // Send notification to the added user
            $sender = Auth::user();
            $receiver = User::find($userId);
            if ($receiver) {
                Notification::create([
                    'from_user_id' => Auth::id(),
                    'to_user_id' => $userId,
                    'type' => 'join_group',
                    'text' => "{$sender->name} added you to {$group->name} group.",
                    'group_id' => $group->id,
                ]);
            }

            $addedCount++;
        }

        return response()->json([
            'status' => 200,
            'message' => __('Api.members_added_successfully'),
            'data' => [
                'added_count' => $addedCount,
                'already_members' => count($alreadyMembers),
                'members_count' => $group->members_count + $addedCount,
            ],
        ], 200);
    }

    /**
     * Get group statistics for dashboard
     */
    public function getGroupStats()
    {
        $userId = Auth::id();

        $totalGroups = Group::count();
        $myGroups = Group::where('user_id', $userId)->count();
        $joinedGroups = Group::whereHas('members', function ($query) use ($userId) {
            $query->where('user_id', $userId);
        })->count();
        $publicGroups = Group::where('privacy', 'public')->count();
        $privateGroups = Group::where('privacy', 'private')->count();
        $featuredGroups = Group::where('is_featured', true)->count();
        $recentGroups = Group::where('created_at', '>=', now()->subDays(7))->count();

        return response()->json([
            'status' => 200,
            'message' => 'Group statistics fetched successfully',
            'data' => [
                'total_groups' => $totalGroups,
                'my_groups' => $myGroups,
                'joined_groups' => $joinedGroups,
                'public_groups' => $publicGroups,
                'private_groups' => $privateGroups,
                'featured_groups' => $featuredGroups,
                'recent_groups' => $recentGroups
            ]
        ], 200);
    }
}
