<?php

namespace App\Synapse;

use App\Models\Claim\Claim;
use App\Models\Document\Document;
use App\Models\Dsar\DsarEvidenceItem;
use App\Models\Institution\Institution;
use App\Synapse\Agents\CareSettingTaggerAgent;
use App\Synapse\Agents\DocumentSourceIdentifierAgent;
use App\Synapse\Context\CareSettingsContext;

/**
 * Shared "suggest, human confirms" AI tagging used by the OCR pipeline (and reusable by the
 * inline extraction jobs). Both operations write suggestions flagged pending until accepted.
 */
class EvidenceAiTagger
{
    /**
     * Suggest a care setting for each of the given items, matching only the claim's existing
     * care settings. Returns the number of items tagged.
     *
     * @param  int[]  $itemIds
     */
    public function tagCareSettings(Claim $claim, array $itemIds): int
    {
        if (empty($itemIds)) {
            return 0;
        }

        $careSettingIds = $claim->careSettings->pluck('id')->all();
        if (empty($careSettingIds)) {
            return 0;
        }

        $items = DsarEvidenceItem::whereIn('id', $itemIds)->get(['id', 'quote']);
        if ($items->isEmpty()) {
            return 0;
        }

        $quoteLines = [];
        $indexToId  = [];
        foreach ($items->values() as $i => $item) {
            $indexToId[$i] = $item->id;
            $quoteLines[]  = "[{$i}] " . trim(mb_substr((string) $item->quote, 0, 500));
        }

        $prompt   = CareSettingsContext::fromClaim($claim) . "\n\nEVIDENCE QUOTES:\n" . implode("\n", $quoteLines);
        $response = (new CareSettingTaggerAgent)->prompt($prompt);
        $mappings = json_decode($response->structured['mappings_json'] ?? '[]', true) ?: [];

        $tagged = 0;
        foreach ($mappings as $m) {
            $idx  = $m['index'] ?? null;
            $csId = $m['care_setting_id'] ?? null;
            $conf = $m['confidence'] ?? 'low';

            if (!isset($indexToId[$idx])
                || !in_array($csId, $careSettingIds, true)
                || !in_array($conf, ['high', 'medium'], true)) {
                continue;
            }

            DsarEvidenceItem::where('id', $indexToId[$idx])->update([
                'care_setting_id'           => $csId,
                'care_setting_is_suggested' => true,
            ]);
            $tagged++;
        }

        return $tagged;
    }

    /**
     * Suggest the source institution for a document that has none. Returns
     * ['institution_id' => ?int, 'confidence' => string] for logging.
     */
    public function suggestDocumentSource(Document $document, string $firstPagesText): array
    {
        if ($document->institution_id) {
            return ['institution_id' => $document->institution_id, 'confidence' => 'existing'];
        }

        $prompt = "Filename: {$document->file_name}\n"
            . "Document type: " . ($document->type?->display_name ?? 'Unknown') . "\n\n"
            . ($firstPagesText !== ''
                ? "First-pages text (OCR'd letterhead / header):\n" . mb_substr($firstPagesText, 0, 6000)
                : "(No text available — infer from filename and type only.)");

        $response      = (new DocumentSourceIdentifierAgent)->prompt($prompt);
        $data          = $response->structured;
        $institutionId = $data['institution_id'] ?? null;
        $confidence    = $data['confidence'] ?? 'low';

        if ($institutionId
            && in_array($confidence, ['high', 'medium'], true)
            && Institution::whereKey($institutionId)->exists()) {
            $document->update([
                'institution_id'           => $institutionId,
                'institution_is_suggested' => true,
            ]);
        }

        return ['institution_id' => $institutionId, 'confidence' => $confidence];
    }
}
