<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Circle;
use App\Models\CircleMember;
use App\Services\SocketIOService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Carbon\Carbon;

class CircleController extends Controller
{
    /**
     * Get all circles of current user
     *
     * GET /api/v1/circles
     */
    public function index(Request $request)
    {
        $circles = $request->user()->circles()->with(['owner:id,name,phone,avatar_url', 'members:id,name,phone,avatar_url'])->get();

        return response()->json([
            'success' => true,
            'data' => $circles,
        ]);
    }

    /**
     * Create a new circle
     *
     * POST /api/v1/circles
     * Body: { name }
     */
    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Validation error',
                'errors' => $validator->errors(),
            ], 422);
        }

        // Circle banao
        $circle = Circle::create([
            'name' => $request->name,
            'user_id' => $request->user()->id,
            'invite_code' => strtoupper(Str::random(3) . '-' . Str::random(3)),
            'invite_code_expires_at' => Carbon::now()->addHours(24),
        ]);

        // Owner ko admin member banao
        CircleMember::create([
            'circle_id' => $circle->id,
            'user_id' => $request->user()->id,
            'role' => 'admin',
        ]);

        $circle->load(['owner:id,name,phone,avatar_url', 'members:id,name,phone,avatar_url']);

        $inviteLink = config('app.url') . '/join?code=' . $circle->invite_code;

        return response()->json([
            'success' => true,
            'message' => 'Circle created successfully',
            'data' => [
                'circle' => $circle,
                'invite_link' => $inviteLink,
            ],
        ], 201);
    }

    /**
     * Get single circle details
     *
     * GET /api/v1/circles/{id}
     */
    public function show(Request $request, $id)
    {
        $circle = Circle::with(['owner:id,name,phone,avatar_url', 'members:id,name,phone,avatar_url', 'places'])
            ->findOrFail($id);

        // Check user is member of this circle
        $isMember = $circle->members()->where('user_id', $request->user()->id)->exists();
        if (!$isMember) {
            return response()->json([
                'success' => false,
                'message' => 'You are not a member of this circle',
            ], 403);
        }

        return response()->json([
            'success' => true,
            'data' => $circle,
        ]);
    }

    /**
     * Update circle name
     *
     * PUT /api/v1/circles/{id}
     * Body: { name }
     */
    public function update(Request $request, $id)
    {
        $circle = Circle::findOrFail($id);

        // Sirf owner/admin update kar sakta hai
        if ($circle->user_id !== $request->user()->id) {
            return response()->json([
                'success' => false,
                'message' => 'Only the circle owner can update it',
            ], 403);
        }

        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Validation error',
                'errors' => $validator->errors(),
            ], 422);
        }

        $circle->update(['name' => $request->name]);

        return response()->json([
            'success' => true,
            'message' => 'Circle updated successfully',
            'data' => $circle,
        ]);
    }

    /**
     * Delete circle
     *
     * DELETE /api/v1/circles/{id}
     */
    public function destroy(Request $request, $id)
    {
        $circle = Circle::findOrFail($id);

        if ($circle->user_id !== $request->user()->id) {
            return response()->json([
                'success' => false,
                'message' => 'Only the circle owner can delete it',
            ], 403);
        }

        $circle->delete();

        // Socket.IO: Notify all members that circle was deleted
        SocketIOService::emitToCircle((int) $id, 'circle-deleted', [
            'circle_id' => (int) $id,
            'circle_name' => $circle->name,
            'deleted_by' => $request->user()->name,
            'timestamp' => now()->toISOString(),
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Circle deleted successfully',
        ]);
    }

    /**
     * Join circle with invite code
     *
     * POST /api/v1/circles/join
     * Body: { invite_code }
     */
    public function join(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'invite_code' => 'required|string',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Validation error',
                'errors' => $validator->errors(),
            ], 422);
        }

        $circle = Circle::where('invite_code', strtoupper($request->invite_code))->first();

        if (!$circle) {
            return response()->json([
                'success' => false,
                'message' => 'Invalid invite code',
            ], 404);
        }

        // Check expiry
        if ($circle->isInviteCodeExpired()) {
            return response()->json([
                'success' => false,
                'message' => 'Invite code has expired. Ask the circle owner for a new code.',
            ], 410);
        }

        // Check already member
        $alreadyMember = CircleMember::where('circle_id', $circle->id)
            ->where('user_id', $request->user()->id)
            ->exists();

        if ($alreadyMember) {
            return response()->json([
                'success' => false,
                'message' => 'You are already a member of this circle',
            ], 409);
        }

        // Add member
        CircleMember::create([
            'circle_id' => $circle->id,
            'user_id' => $request->user()->id,
            'role' => 'member',
        ]);

        $circle->load(['owner:id,name,phone,avatar_url', 'members:id,name,phone,avatar_url']);

        // Socket.IO: Notify circle members that a new member joined
        SocketIOService::emitToCircle($circle->id, 'member-joined', [
            'circle_id' => $circle->id,
            'circle_name' => $circle->name,
            'user_id' => $request->user()->id,
            'name' => $request->user()->name,
            'phone' => $request->user()->phone,
            'avatar_url' => $request->user()->avatar_url,
            'timestamp' => now()->toISOString(),
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Successfully joined the circle',
            'data' => $circle,
        ]);
    }

    /**
     * Leave circle
     *
     * POST /api/v1/circles/{id}/leave
     */
    public function leave(Request $request, $id)
    {
        $circle = Circle::findOrFail($id);

        // Owner leave nahi kar sakta — usse delete karna padega
        if ($circle->user_id === $request->user()->id) {
            return response()->json([
                'success' => false,
                'message' => 'Circle owner cannot leave. Delete the circle instead.',
            ], 403);
        }

        CircleMember::where('circle_id', $circle->id)
            ->where('user_id', $request->user()->id)
            ->delete();

        // Socket.IO: Notify circle members that someone left
        SocketIOService::emitToCircle($circle->id, 'member-left', [
            'circle_id' => $circle->id,
            'circle_name' => $circle->name,
            'user_id' => $request->user()->id,
            'name' => $request->user()->name,
            'timestamp' => now()->toISOString(),
        ]);

        return response()->json([
            'success' => true,
            'message' => 'You have left the circle',
        ]);
    }

    /**
     * Remove member from circle (owner only)
     *
     * POST /api/v1/circles/{id}/remove-member
     * Body: { user_id }
     */
    public function removeMember(Request $request, $id)
    {
        $circle = Circle::findOrFail($id);

        if ($circle->user_id !== $request->user()->id) {
            return response()->json([
                'success' => false,
                'message' => 'Only the circle owner can remove members',
            ], 403);
        }

        $validator = Validator::make($request->all(), [
            'user_id' => 'required|integer|exists:users,id',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Validation error',
                'errors' => $validator->errors(),
            ], 422);
        }

        // Owner khud ko remove nahi kar sakta
        if ($request->user_id === $circle->user_id) {
            return response()->json([
                'success' => false,
                'message' => 'Cannot remove the circle owner',
            ], 403);
        }

        CircleMember::where('circle_id', $circle->id)
            ->where('user_id', $request->user_id)
            ->delete();

        // Socket.IO: Notify the removed user + circle members
        $removedUser = \App\Models\User::find($request->user_id);
        SocketIOService::emitToCircle($circle->id, 'member-removed', [
            'circle_id' => $circle->id,
            'circle_name' => $circle->name,
            'user_id' => $request->user_id,
            'name' => $removedUser ? $removedUser->name : 'Unknown',
            'removed_by' => $request->user()->name,
            'timestamp' => now()->toISOString(),
        ]);
        // Removed user ko bhi notify karo
        SocketIOService::emitToUser($request->user_id, 'member-removed', [
            'circle_id' => $circle->id,
            'circle_name' => $circle->name,
            'removed_by' => $request->user()->name,
            'timestamp' => now()->toISOString(),
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Member removed successfully',
        ]);
    }

    /**
     * Regenerate invite code (owner only)
     *
     * POST /api/v1/circles/{id}/regenerate-code
     */
    public function regenerateCode(Request $request, $id)
    {
        $circle = Circle::findOrFail($id);

        if ($circle->user_id !== $request->user()->id) {
            return response()->json([
                'success' => false,
                'message' => 'Only the circle owner can regenerate the invite code',
            ], 403);
        }

        $circle->generateInviteCode();

        $inviteLink = config('app.url') . '/join?code=' . $circle->invite_code;

        return response()->json([
            'success' => true,
            'message' => 'Invite code regenerated successfully',
            'data' => [
                'invite_code' => $circle->invite_code,
                'invite_code_expires_at' => $circle->invite_code_expires_at,
                'invite_link' => $inviteLink,
            ],
        ]);
    }

    /**
     * Get circle members with their latest locations
     *
     * GET /api/v1/circles/{id}/members-locations
     */
    public function membersLocations(Request $request, $id)
    {
        $circle = Circle::findOrFail($id);

        // Check user is member
        $isMember = $circle->members()->where('user_id', $request->user()->id)->exists();
        if (!$isMember) {
            return response()->json([
                'success' => false,
                'message' => 'You are not a member of this circle',
            ], 403);
        }

        $members = $circle->members()
            ->select('users.id', 'users.name', 'users.phone', 'users.avatar_url')
            ->with('latestLocation')
            ->get();

        return response()->json([
            'success' => true,
            'data' => $members,
        ]);
    }
}
