<?php

namespace App\Synapse\Agents;

use App\Synapse\Tools\SearchDsarByReferenceTool;
use App\Synapse\Tools\SearchInstitutionsTool;
use App\Synapse\Tools\SearchOpenDsarsTool;
use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Ai\Attributes\MaxTokens;
use Laravel\Ai\Attributes\Model;
use Laravel\Ai\Attributes\Provider;
use Laravel\Ai\Attributes\Timeout;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\HasStructuredOutput;
use Laravel\Ai\Contracts\HasTools;
use Laravel\Ai\Promptable;
use Stringable;

#[Provider('openai')]
#[Model('gpt-4o')]
#[MaxTokens(1000)]
#[Timeout(90)]
class DsarMatcherAgent implements Agent, HasStructuredOutput, HasTools
{
    use Promptable;

    public function tools(): iterable
    {
        return [
            new SearchDsarByReferenceTool(),
            new SearchInstitutionsTool(),
            new SearchOpenDsarsTool(),
        ];
    }

    public function instructions(): Stringable|string
    {
        return <<<'SYSTEM'
You are a DSAR matching assistant for a legal claims management firm. You will be given an inbound email that has been classified as a Data Subject Access Request (DSAR) response. Your task is to identify which specific open DSAR this email is responding to.

The prompt may include an "EXTRACTED REFERENCE NUMBERS" section at the bottom with pre-extracted references — use these as your starting point.

Follow these steps in order:

1. Try reference matching first (fastest and most reliable):
   - Check the EXTRACTED REFERENCE NUMBERS section for an institution reference
   - Also scan the email for institution reference patterns (e.g., "Our ref:", "Case ref:", "SAR/2024/...")
   - If a reference is found, call SearchDsarByReferenceTool with it
   - A single matching DSAR found this way = high confidence; stop here if confident

2. Identify the sending institution (if reference matching failed or was inconclusive):
   - Extract the institution name from the sender's email address domain (e.g., cddft.nhs.uk → County Durham & Darlington NHS Foundation Trust)
   - Look for institution names, departments, or NHS trust names in the subject line and email body

3. Search for the institution:
   - Use SearchInstitutionsTool to find the institution in the database
   - Try multiple search terms if the first attempt returns no results (trust name, shortened version, acronym)

4. Extract client full name (structured patterns only):
   - Look for the data subject's full name (first AND last name together) in:
     - The subject line (e.g. "Re: Data Subject Access Request - John Smith")
     - A formal "Re:", "Regarding:", or "DATA SUBJECT:" line in the letter header
     - An "In the matter of:" or equivalent opening line
   - Do NOT use the email salutation ("Dear John") — it may refer to our claim handler, not the client
   - Only use a full name you are confident refers to the data subject

5. Find matching open DSARs by institution:
   - Use SearchOpenDsarsTool with the institution_id
   - If a client full name was found in step 4, pass it as client_name to narrow the results
   - If multiple DSARs still exist, pick the most likely match based on:
     - The timing (most recently sent DSAR is most likely)
     - The DSAR status (prefer 'sent' over 'approved')

6. Confidence ratings:
   - high: Direct reference match OR institution clearly identified with a single obvious DSAR
   - medium: Institution identified but multiple DSARs exist, OR institution match is approximate
   - low: Institution uncertain or no DSARs found
SYSTEM;
    }

    public function schema(JsonSchema $schema): array
    {
        return [
            'institution_id' => $schema
                ->integer()
                ->nullable()
                ->description('The institution ID from the database, or null if not identified')
                ->required(),
            'dsar_id' => $schema
                ->integer()
                ->nullable()
                ->description('The ID of the matching open DSAR, or null if not found')
                ->required(),
            'confidence' => $schema
                ->string()
                ->description('One of: high, medium, low')
                ->required(),
            'reasoning' => $schema
                ->string()
                ->description('Brief explanation of how the match was determined')
                ->required(),
        ];
    }
}
