<?php

namespace App\Http\Controllers\Frontend;

use App\Http\Controllers\Controller;
use App\Models\VoiceCall;
use App\Models\User;
use App\Services\AgoraTokenService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;

class VoiceCallController extends Controller
{
    public function initiate(Request $request)
    {
        $request->validate(['callee_id' => 'required|integer|exists:users,id']);
        $caller = Auth::user();
        $callee = User::findOrFail($request->callee_id);

        if ($caller->id === $callee->id) {
            return response()->json(['error' => 'Kendinizi arayamazsınız.'], 422);
        }

        // End any previous active calls
        VoiceCall::where('caller_id', $caller->id)
            ->whereIn('status', ['ringing', 'active'])
            ->update(['status' => 'ended', 'ended_at' => now()]);

        $channelName = 'vc_' . Str::random(20);
        $call = VoiceCall::create([
            'caller_id'    => $caller->id,
            'callee_id'    => $callee->id,
            'channel_name' => $channelName,
            'status'       => 'ringing',
        ]);

        $callerToken = AgoraTokenService::generateToken($channelName, $caller->id);
        $calleeToken = AgoraTokenService::generateToken($channelName, $callee->id);

        return response()->json([
            'call_id'      => $call->id,
            'channel_name' => $channelName,
            'token'        => $callerToken,
            'callee'       => [
                'id'     => $callee->id,
                'name'   => $callee->name,
                'avatar' => $callee->avatar ? \App\Support\MediaUrl::fromStoragePath($callee->avatar) : null,
            ],
            'agora_app_id' => env('AGORA_APP_ID', ''),
        ]);
    }

    public function answer(VoiceCall $call)
    {
        $user = Auth::user();
        abort_unless($call->callee_id === $user->id, 403);
        abort_unless($call->status === 'ringing', 422, 'Call is no longer ringing.');

        $call->update(['status' => 'active', 'answered_at' => now()]);

        $token = AgoraTokenService::generateToken($call->channel_name, $user->id);

        return response()->json([
            'channel_name' => $call->channel_name,
            'token'        => $token,
            'agora_app_id' => env('AGORA_APP_ID', ''),
            'caller'       => [
                'id'     => $call->caller->id,
                'name'   => $call->caller->name,
                'avatar' => $call->caller->avatar ? \App\Support\MediaUrl::fromStoragePath($call->caller->avatar) : null,
            ],
        ]);
    }

    public function decline(VoiceCall $call)
    {
        $user = Auth::user();
        abort_unless($call->callee_id === $user->id || $call->caller_id === $user->id, 403);
        abort_unless($call->status === 'ringing', 422);

        $call->update(['status' => 'declined', 'ended_at' => now()]);

        return response()->json(['ok' => true]);
    }

    public function end(VoiceCall $call)
    {
        $user = Auth::user();
        abort_unless($call->callee_id === $user->id || $call->caller_id === $user->id, 403);

        $call->update(['status' => 'ended', 'ended_at' => now()]);

        return response()->json(['ok' => true]);
    }

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

        // Check for incoming ringing call
        $incoming = VoiceCall::where('callee_id', $user->id)
            ->where('status', 'ringing')
            ->with('caller')
            ->latest()
            ->first();

        if ($incoming) {
            return response()->json([
                'type'    => 'incoming',
                'call_id' => $incoming->id,
                'caller'  => [
                    'id'     => $incoming->caller->id,
                    'name'   => $incoming->caller->name,
                    'avatar' => $incoming->caller->avatar ? \App\Support\MediaUrl::fromStoragePath($incoming->caller->avatar) : null,
                ],
            ]);
        }

        // Check if an active call we're in has been ended by the other side
        $call_id = $request->query('call_id');
        if ($call_id) {
            $call = VoiceCall::find($call_id);
            if ($call && in_array($user->id, [$call->caller_id, $call->callee_id])) {
                return response()->json([
                    'type'   => 'status',
                    'status' => $call->status,
                ]);
            }
        }

        return response()->json(['type' => 'none']);
    }
}
