<?php

namespace App\Jobs\Synapse;

use App\Models\Synapse\SynapseTranscript;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class CheckTranscriptionStatusJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public int $tries   = 3;
    public int $timeout = 90;   // extended to allow for LeMUR summary call
    public int $backoff = 15;

    /** Maximum polling attempts before giving up (~3 hours at 60s intervals). */
    private const MAX_CHECKS = 180;

    public function __construct(
        public readonly int    $recordingId,
        public readonly string $assemblyAiId,
        public readonly int    $checkCount = 0,
    ) {}

    public function handle(): void
    {
        if ($this->checkCount >= self::MAX_CHECKS) {
            SynapseTranscript::where('recording_id', $this->recordingId)
                ->update(['status' => 'failed', 'error' => 'Transcription timed out after ' . self::MAX_CHECKS . ' polling attempts.']);

            Log::error("CheckTranscriptionStatusJob: timed out for recording {$this->recordingId} (AssemblyAI {$this->assemblyAiId}).");
            return;
        }

        $response = Http::withHeaders(['Authorization' => config('synapse.assemblyai_key')])
            ->timeout(15)
            ->throw()
            ->get("https://api.assemblyai.com/v2/transcript/{$this->assemblyAiId}");

        $status = $response->json('status');

        Log::debug("CheckTranscriptionStatusJob: recording {$this->recordingId} → AssemblyAI status={$status} (check #{$this->checkCount})");

        if (in_array($status, ['queued', 'processing'])) {
            // Not done yet — re-check in 60 seconds.
            self::dispatch($this->recordingId, $this->assemblyAiId, $this->checkCount + 1)
                ->delay(now()->addSeconds(60));
            return;
        }

        if ($status === 'completed') {
            $data          = $response->json();
            $raw           = $this->formatTranscript($data);
            $sentimentData = $data['sentiment_analysis_results'] ?? null;

            SynapseTranscript::where('recording_id', $this->recordingId)
                ->update([
                    'status'               => 'completed',
                    'raw_transcript'       => $raw,
                    'formatted_transcript' => $raw,
                    'sentiment_data'       => $sentimentData ? json_encode($sentimentData) : null,
                    'error'                => null,
                ]);

            Log::info("CheckTranscriptionStatusJob: completed for recording {$this->recordingId} after {$this->checkCount} checks.");

            // Fetch a LeMUR summary from AssemblyAI (non-critical — failure is logged and ignored).
            $this->fetchLemurSummary($this->assemblyAiId, $this->recordingId);

            ClassifyAndScoreCallJob::dispatch($this->recordingId);
            return;
        }

        // AssemblyAI returned 'error'.
        $errorMessage = $response->json('error') ?? 'Unknown AssemblyAI error';

        SynapseTranscript::where('recording_id', $this->recordingId)
            ->update(['status' => 'failed', 'error' => $errorMessage]);

        Log::error("CheckTranscriptionStatusJob: AssemblyAI error for recording {$this->recordingId}.", [
            'assemblyai_id' => $this->assemblyAiId,
            'error'         => $errorMessage,
        ]);
    }

    /**
     * Call AssemblyAI LeMUR to generate a plain-English call summary and persist it.
     * Failure is silently logged — the transcript is already saved.
     */
    protected function fetchLemurSummary(string $assemblyAiId, int $recordingId): void
    {
        try {
            $response = Http::withHeaders(['Authorization' => config('synapse.assemblyai_key')])
                ->timeout(45)
                ->post('https://api.assemblyai.com/lemur/v3/generate/task', [
                    'transcript_ids' => [$assemblyAiId],
                    'prompt'         => 'Summarise this call in 2–4 sentences. Focus on: the purpose of the call, what was discussed, and the outcome.',
                    'final_model'    => config('synapse.lemur_model', 'anthropic/claude-3-5-haiku'),
                    'max_output_size' => 500,
                ]);

            if (!$response->successful()) {
                Log::warning("CheckTranscriptionStatusJob: LeMUR summary failed for recording {$recordingId}.", [
                    'status' => $response->status(),
                    'body'   => $response->body(),
                ]);
                return;
            }

            $summary = $response->json('response');

            if (filled($summary)) {
                SynapseTranscript::where('recording_id', $recordingId)
                    ->update(['ai_summary' => $summary]);

                Log::debug("CheckTranscriptionStatusJob: LeMUR summary saved for recording {$recordingId}.");
            }
        } catch (\Throwable $e) {
            Log::warning("CheckTranscriptionStatusJob: LeMUR summary exception for recording {$recordingId}.", [
                'error' => $e->getMessage(),
            ]);
        }
    }

    protected function formatTranscript(array $data): string
    {
        // Use utterances (speaker-diarized) when available, fall back to plain text.
        if (!empty($data['utterances'])) {
            return collect($data['utterances'])
                ->map(function (array $utterance) {
                    $speaker   = $utterance['speaker'] ?? 'Speaker';
                    $start     = (int) (($utterance['start'] ?? 0) / 1000); // ms → seconds
                    $timestamp = sprintf('%02d:%02d', intdiv($start, 60), $start % 60);
                    $text      = trim($utterance['text'] ?? '');

                    return "[{$speaker} {$timestamp}]: {$text}";
                })
                ->implode("\n");
        }

        return $data['text'] ?? '';
    }
}
