<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Incident;
use App\Models\NotificationDelivery;
use App\Services\VoiceCallService;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

/**
 * Receives Twilio Voice webhooks: TwiML fetches and gather responses.
 *
 * Three endpoints:
 *
 *   GET/POST /api/voice/twiml/{incident}   — Twilio fetches TwiML to know
 *                                            what to say to the recipient
 *   POST    /api/voice/respond/{incident}  — Twilio sends keypad digits
 *                                            after the user presses a button
 *   POST    /api/voice/status/{incident}   — Call lifecycle (ringing,
 *                                            answered, completed) for tracking
 *
 * All return XML (TwiML) or 204 — Twilio doesn't care about JSON.
 */
class VoiceWebhookController extends Controller
{
    public function __construct(protected VoiceCallService $voice) {}

    public function twiml(Incident $incident): Response
    {
        return response($this->voice->buildTwiml($incident), 200)
            ->header('Content-Type', 'text/xml');
    }

    public function respond(Request $request, Incident $incident): Response
    {
        $digit = $request->input('Digits', '');
        // The user identity comes from the From number — we map it back to
        // a User record via the most recent voice delivery for this incident.
        $callerNumber = $request->input('From', '');
        $delivery = NotificationDelivery::where('subject_type', Incident::class)
            ->where('subject_id', $incident->id)
            ->where('channel_key', 'voice')
            ->where('recipient_address', $callerNumber)
            ->latest()
            ->first();
        $user = $delivery?->recipient_user_id
            ? \App\Models\User::find($delivery->recipient_user_id)
            : null;

        $xml = $this->voice->handleResponse($incident, $digit, $user);
        return response($xml, 200)->header('Content-Type', 'text/xml');
    }

    public function status(Request $request, Incident $incident): Response
    {
        $callSid = $request->input('CallSid');
        $status = $request->input('CallStatus');

        // Twilio's CallSid lives in `response.sid` (we stored the full Twilio
        // payload in `response` column on dispatch). Use a JSON-path lookup.
        $delivery = NotificationDelivery::where('subject_type', Incident::class)
            ->where('subject_id', $incident->id)
            ->where('channel_key', 'voice')
            ->whereJsonContains('response->sid', $callSid)
            ->latest()
            ->first();

        if ($delivery) {
            $delivery->update([
                'status' => match ($status) {
                    'completed' => 'sent',
                    'no-answer', 'busy', 'failed', 'canceled' => 'failed',
                    default => $delivery->status,
                },
                'sent_at' => $status === 'completed' ? now() : $delivery->sent_at,
                'failed_at' => in_array($status, ['no-answer', 'busy', 'failed', 'canceled'])
                    ? now() : $delivery->failed_at,
            ]);
        }

        return response('', 204);
    }
}
