<?php
/**
 * generate-mcp-translations.php
 * One-shot CLI script: php scripts/generate-mcp-translations.php
 *
 * Produces two files:
 *   1. translations/mcp-chrome.php  — UI chrome strings for mcp.php + mcp-tool.php
 *   2. includes/mcp-tool-translations.php — tool names, descriptions, param docs in all 4 languages
 */
declare(strict_types=1);

define('SCRIPT_MODE', true);
require_once dirname(__DIR__) . '/includes/bootstrap.php';

// ─────────────────────────────────────────────────────────────────────────────
// Azure config (same pattern as generate-page-translations.php)
// ─────────────────────────────────────────────────────────────────────────────
$azConfig = [
    'endpoint'        => rtrim((string)dbnToolsEnv('DBN_AZURE_OPENAI_ENDPOINT', ''), '/'),
    'api_key'         => (string)dbnToolsEnv('DBN_AZURE_OPENAI_API_KEY', ''),
    'api_version'     => (string)dbnToolsEnv('DBN_AZURE_OPENAI_API_VERSION', '2024-02-01'),
    'chat_deployment' => (string)dbnToolsEnv('DBN_AZURE_OPENAI_CHAT_DEPLOYMENT', 'gpt-4o-mini'),
];

function azureChat(array $config, array $messages, array $options = []): array
{
    $url = $config['endpoint']
        . '/openai/deployments/'
        . rawurlencode($config['chat_deployment'])
        . '/chat/completions?api-version='
        . rawurlencode($config['api_version']);

    $payload = json_encode(array_filter([
        'messages'        => $messages,
        'temperature'     => $options['temperature'] ?? 0.1,
        'max_tokens'      => $options['max_tokens'] ?? 4096,
        'response_format' => isset($options['json']) && $options['json']
            ? ['type' => 'json_object'] : null,
    ], fn($v) => $v !== null), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => $payload,
        CURLOPT_HTTPHEADER     => [
            'Content-Type: application/json',
            'api-key: ' . $config['api_key'],
        ],
        CURLOPT_TIMEOUT        => (int)($options['timeout'] ?? 120),
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
    ]);

    $body = curl_exec($ch);
    $code = (int)curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    $err  = curl_error($ch);
    curl_close($ch);

    if ($body === false) throw new RuntimeException("Azure curl failed: $err");
    $decoded = json_decode($body, true);
    if (!is_array($decoded)) throw new RuntimeException("Azure returned non-JSON (HTTP $code)");
    if ($code < 200 || $code >= 300) {
        throw new RuntimeException('Azure error: ' . ($decoded['error']['message'] ?? "HTTP $code"));
    }
    return $decoded;
}

$languages = [
    'no' => 'Norwegian (Norsk bokmål)',
    'uk' => 'Ukrainian',
    'pl' => 'Polish',
];

$systemPrompt = <<<'PROMPT'
You are a professional legal translator specializing in Norwegian family law and child welfare.
Translate all JSON string values to {LANG}.

PRESERVE AS-IS:
- Norwegian institution names: Barnevernet, Statsforvalteren, Bufdir, Fylkesnemnda, NAV, Tingretten
- Norwegian legal act names: forvaltningsloven, barnevernsloven, opplæringslova, EMK, fvl
- Norwegian legal terms: klage, vedtak, saksnummer, akutt, omsorgsovertakelse, tiltaksplan
- Technical terms: MCP, DBN, dbn.tool_name, JSON, Bearer token, npx, stdio
- Brand names: Do Better Norge, Claude, Cursor, VS Code, Windsurf, Copilot
- Code snippets, URLs, env var names like DBN_MCP_TOKEN
- HTML entities and tags exactly as they appear
- The symbol ← and →

Return a JSON object with EXACTLY the same keys as the input. Translate only the string values.
Use formal/professional register appropriate for a legal tools platform.
PROMPT;

function translateBatch(array $azConfig, string $langName, string $systemPrompt, array $batch): array
{
    $prompt   = str_replace('{LANG}', $langName, $systemPrompt);
    $json     = json_encode($batch, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    $response = azureChat($azConfig, [
        ['role' => 'system', 'content' => $prompt],
        ['role' => 'user',   'content' => $json],
    ], ['json' => true, 'max_tokens' => 4096, 'timeout' => 120]);

    $content = trim((string)($response['choices'][0]['message']['content'] ?? ''));
    $decoded = json_decode($content, true);
    if (!is_array($decoded)) {
        echo "    [WARN] JSON parse failed, trying extraction...\n";
        if (preg_match('/\{.*\}/s', $content, $m)) {
            $decoded = json_decode($m[0], true);
        }
    }
    if (!is_array($decoded)) {
        echo "    [ERROR] Could not parse response, using English fallback\n";
        return $batch;
    }
    foreach ($batch as $k => $v) {
        if (!isset($decoded[$k])) $decoded[$k] = $v;
    }
    return $decoded;
}

function writePhpFile(string $path, array $data, string $comment): void
{
    $php = "<?php\n// $comment\n// DO NOT EDIT MANUALLY — regenerate with scripts/generate-mcp-translations.php\nreturn ";
    $php .= var_export($data, true);
    $php .= ";\n";
    file_put_contents($path, $php);
}

// ─────────────────────────────────────────────────────────────────────────────
// Part 1 — MCP UI chrome strings
// ─────────────────────────────────────────────────────────────────────────────
$chromeEn = [
    // mcp.php
    'mcp_page_title'             => 'MCP — Do Better Norge',
    'mcp_meta_desc'              => 'Connect Claude, Cursor, and other AI tools to all 19 DBN legal preparation tools via MCP.',
    'mcp_hero_badge'             => '✦ Plus & Pro',
    'mcp_hero_h1'                => 'Use DBN tools from Claude, Cursor & Copilot',
    'mcp_hero_sub'               => 'Connect any MCP client to all 19 Do Better Norge tools — transcription, legal analysis, timelines, redaction, and more.',
    'mcp_token_section_title'    => 'Your MCP token',
    'mcp_gate_guest_p'           => 'Sign in to create your personal MCP token. Available to Plus and Pro members.',
    'mcp_gate_guest_btn'         => 'Sign in',
    'mcp_gate_free_p'            => 'MCP access is available on Plus and Pro plans. Upgrade to connect your AI tools.',
    'mcp_gate_free_btn'          => 'Upgrade plan',
    'mcp_token_hint'             => 'Tokens are shown once at creation. Create one per client (Claude, Cursor, VS Code…).',
    'mcp_token_create_btn'       => 'Create token',
    'mcp_token_reveal_label'     => 'Copy this token now — it will not be shown again:',
    'mcp_token_copy_btn'         => 'Copy token',
    'mcp_token_no_tokens'        => 'No MCP tokens yet.',
    'mcp_token_active'           => 'Active',
    'mcp_token_revoked'          => 'Revoked',
    'mcp_token_never_used'       => 'Never used',
    'mcp_token_last_used'        => 'Last used',
    'mcp_token_revoke_btn'       => 'Revoke',
    'mcp_config_title'           => 'Client configuration',
    'mcp_config_hint'            => 'Paste your token into the config below after creating it above.',
    'mcp_config_token_filled'    => 'Token auto-filled.',
    'mcp_config_run_terminal'    => 'Run in your terminal:',
    'mcp_test_btn'               => 'Test connection',
    'mcp_test_no_token'          => 'Create a token first.',
    'mcp_test_testing'           => 'Testing…',
    'mcp_tools_title'            => 'Available tools',
    'mcp_tools_sub'              => 'All tools run on your Plus or Pro plan credits. Click a card for full technical details.',
    'mcp_tools_param_req_hint'   => 'Purple = required',
    'mcp_tools_view_details'     => 'View details →',
    // privacy section
    'mcp_privacy_title'          => 'Privacy',
    'mcp_privacy_text'           => 'Process-and-forget by default. All tool calls process your text in memory and return results to your AI client. Nothing is saved to My Case unless you explicitly call dbn.save_to_case.',
    'mcp_privacy_legal'          => 'Tools provide legal preparation support, not final legal advice. Results are for informational purposes and should be reviewed by a qualified legal professional.',
    // mcp-tool.php
    'mcp_tool_back'              => '← Back to MCP setup',
    'mcp_tool_params_title'      => 'Parameters',
    'mcp_tool_no_params'         => 'This tool takes no input parameters.',
    'mcp_tool_col_param'         => 'Parameter',
    'mcp_tool_col_type'          => 'Type',
    'mcp_tool_col_required'      => 'Required',
    'mcp_tool_col_desc'          => 'Description',
    'mcp_tool_example_req'       => 'Example request',
    'mcp_tool_example_resp'      => 'Example response',
    'mcp_tool_connect_title'     => 'Connect',
    'mcp_tool_connect_text'      => 'Create your MCP token on the setup page and use it with any supported client.',
    'mcp_tool_setup_link'        => 'Set up MCP →',
    'mcp_tool_yes'               => 'Yes',
    'mcp_tool_no'                => 'No',
];

echo "\n=== Part 1: Translating MCP UI chrome strings ===\n";
$chromeTranslations = ['en' => $chromeEn];
$batchSize = 20;
$keys      = array_keys($chromeEn);
$batches   = array_chunk($keys, $batchSize);

foreach ($languages as $langCode => $langName) {
    echo "  Language: $langName ($langCode)\n";
    $langResult = [];
    foreach ($batches as $idx => $batchKeys) {
        $batchNum = $idx + 1;
        echo "    Batch $batchNum/" . count($batches) . " (" . count($batchKeys) . " strings)...\n";
        $batchInput = [];
        foreach ($batchKeys as $k) $batchInput[$k] = $chromeEn[$k];
        $langResult = array_merge($langResult, translateBatch($azConfig, $langName, $systemPrompt, $batchInput));
    }
    $chromeTranslations[$langCode] = $langResult;
}

$chromeOutPath = dirname(__DIR__) . '/translations/mcp-chrome.php';
writePhpFile($chromeOutPath, $chromeTranslations, 'MCP UI chrome translations — mcp.php + mcp-tool.php');
echo "  Written: $chromeOutPath\n";

// ─────────────────────────────────────────────────────────────────────────────
// Part 2 — MCP tool content (display_name, description, param descriptions)
// ─────────────────────────────────────────────────────────────────────────────

// English source for all tool content — param descriptions are authored here
// since DbnMcpRuntime.php params mostly lack description fields.
$toolsEn = [
    'dbn.search_legal' => [
        'display_name' => 'Search DBN legal corpus',
        'description'  => 'Search the DBN Norwegian family-law corpus.',
        'params'       => [
            'query'        => 'The search query (minimum 3 characters). Enter a legal topic, keyword, or question.',
            'language'     => 'Response language: en, no, uk, pl, or auto (detect from input).',
            'limit'        => 'Maximum number of results to return (1–10).',
            'corpus_scope' => 'Which corpus to search: shared (public legal corpus), private (your uploaded documents), or both.',
        ],
    ],
    'dbn.ask' => [
        'display_name' => 'Ask a legal question',
        'description'  => 'Answer a legal preparation question with source-grounded DBN context.',
        'params'       => [
            'question'         => 'The legal question to answer (minimum 5 characters).',
            'language'         => 'Response language: en, no, uk, pl, or auto.',
            'use_case_context' => 'Include context from your Case Workbench session (true/false).',
        ],
    ],
    'dbn.summarize' => [
        'display_name' => 'Summarize document',
        'description'  => 'Summarize pasted case text with optional legal-corpus enrichment.',
        'params'       => [
            'text'             => 'The text to summarize.',
            'language'         => 'Response language: en, no, uk, pl, or auto.',
            'use_legal_corpus' => 'Enrich the summary with relevant legal corpus passages (true/false).',
            'use_case_context' => 'Include context from your Case Workbench session (true/false).',
        ],
    ],
    'dbn.timeline' => [
        'display_name' => 'Extract timeline',
        'description'  => 'Extract dates, hearings, milestones, and deadlines from case text.',
        'params'       => [
            'text'             => 'The case text to extract dates from.',
            'language'         => 'Response language: en, no, uk, pl, or auto.',
            'focus'            => 'What to extract: all (every date), deadlines (appeal windows and filing deadlines), hearings (tribunal and court dates), cps (Barnevernet milestones).',
            'use_case_context' => 'Include context from your Case Workbench session (true/false).',
        ],
    ],
    'dbn.redact' => [
        'display_name' => 'Redact private data',
        'description'  => 'Remove or pseudonymize names, IDs, phone numbers, addresses, and places.',
        'params'       => [
            'text'          => 'The text to redact.',
            'language'      => 'Language of the input text: en, no, uk, pl, or auto.',
            'mode'          => 'Redaction scope: standard (names, IDs, phones) or strict (also addresses, locations, institutions).',
            'output_format' => 'Replacement style: contextual ([PERSON A]), generic (█████), or pseudonym (consistent invented names).',
        ],
    ],
    'dbn.translate' => [
        'display_name' => 'Translate legal document',
        'description'  => 'Translate Norwegian family-law text with legal terminology annotations.',
        'params'       => [
            'text'        => 'The text to translate.',
            'source_lang' => 'Language of the input text. Use auto to detect automatically.',
            'target_lang' => 'Language to translate into (required): en, no, uk, or pl.',
            'doc_type'    => 'Document type hint for legal terminology: auto, barnevernet, adopsjon, emergency, samvaer, fylkesnemnd, or other.',
        ],
    ],
    'dbn.legal_analysis' => [
        'display_name' => 'Legal analysis',
        'description'  => 'Extract legal issues from a document and answer each with DBN legal context.',
        'params'       => [
            'text'     => 'The document text to analyze.',
            'language' => 'Response language: en, no, uk, pl, or auto.',
            'doc_type' => 'Document type hint: auto, barnevernet, adopsjon, emergency, samvaer, fylkesnemnd, or other.',
        ],
    ],
    'dbn.korrespond' => [
        'display_name' => 'Draft authority correspondence',
        'description'  => 'Draft a reply or new letter to Norwegian authorities.',
        'params'       => [
            'narrative'        => 'Description of your situation — what happened and what you need.',
            'received_text'    => 'Text of the letter or decision you received (for reply mode).',
            'recipient_body'   => 'The authority you are writing to (e.g. Barnevernet, NAV, Skole, Kommune).',
            'goal'             => 'Your legal goal — what you want the letter to achieve.',
            'mode'             => 'reply (responding to a received letter) or initiate (starting new correspondence).',
            'language'         => 'Response language: en, no, uk, pl, or auto.',
            'use_case_context' => 'Include context from your Case Workbench session (true/false).',
            'force_draft'      => 'Skip the clarify gate and draft immediately (true/false).',
        ],
    ],
    'dbn.barnevernet_analyze' => [
        'display_name' => 'Analyze Barnevernet document',
        'description'  => 'Analyze child-welfare documents for red flags and legal issues.',
        'params'       => [
            'document_text'    => 'Full text of the child welfare document to analyze (required).',
            'filename'         => 'Original filename for context (helps identify document type).',
            'advocate_role'    => 'Your role in the case: parent, lawyer, guardian ad litem, etc.',
            'language'         => 'Response language: en, no, uk, pl, or auto.',
            'use_case_context' => 'Include context from your Case Workbench session (true/false).',
        ],
    ],
    'dbn.advocate_brief' => [
        'display_name' => 'Create advocate brief',
        'description'  => 'Generate a source-grounded brief for a chosen party or role.',
        'params'       => [
            'query'            => 'Legal question or topic for the brief.',
            'paste_text'       => 'Document text to use as the basis for the brief.',
            'advocate_role'    => 'The party or role to advocate for (required). E.g. parent, child, Barnevernet.',
            'language'         => 'Response language: en, no, uk, pl, or auto.',
            'use_case_context' => 'Include context from your Case Workbench session (true/false).',
        ],
    ],
    'dbn.deep_research' => [
        'display_name' => 'Deep research',
        'description'  => 'Expand a legal question into research angles and synthesize a cited brief.',
        'params'       => [
            'query'            => 'Legal question to research in depth.',
            'paste_text'       => 'Supporting document text to research from.',
            'language'         => 'Response language: en, no, uk, pl, or auto.',
            'use_case_context' => 'Include context from your Case Workbench session (true/false).',
        ],
    ],
    'dbn.discrepancy_find' => [
        'display_name' => 'Find document discrepancies',
        'description'  => 'Compare two document versions for contradictions, deletions, and added claims.',
        'params'       => [
            'document_a_text' => 'Text of the first document (required).',
            'document_b_text' => 'Text of the second document to compare against the first (required).',
            'filename_a'      => 'Filename of the first document (for reference in the report).',
            'filename_b'      => 'Filename of the second document (for reference in the report).',
            'language'        => 'Response language: en, no, uk, pl, or auto.',
        ],
    ],
    'dbn.transcribe_audio' => [
        'display_name' => 'Transcribe audio',
        'description'  => 'Transcribe an audio file from base64-encoded content or a URL.',
        'params'       => [
            'audio_base64' => 'Base64-encoded audio file content. Use either this or audio_url.',
            'audio_url'    => 'URL to a publicly accessible audio file. Use either this or audio_base64.',
            'filename'     => 'Original filename with extension (e.g. recording.mp3) — helps set the correct audio format.',
            'language'     => 'Language spoken in the audio (e.g. no, en, uk). Leave blank for auto-detection.',
            'diarize'      => 'Enable speaker diarization — label each segment with a speaker identifier (true/false).',
        ],
    ],
    'dbn.corpus_stats' => [
        'display_name' => 'Corpus statistics',
        'description'  => 'Return document and chunk counts and active legal sources in the DBN corpus.',
        'params'       => [],
    ],
    'dbn.list_documents' => [
        'display_name' => 'List corpus documents',
        'description'  => 'List DBN legal corpus documents with optional filters.',
        'params'       => [
            'category' => 'Filter by document category (e.g. barnevernet, statsforvalter, echr).',
            'title'    => 'Filter by title — partial match.',
            'limit'    => 'Maximum number of documents to return (1–50, default 20).',
            'offset'   => 'Number of documents to skip (for pagination).',
        ],
    ],
    'dbn.get_document' => [
        'display_name' => 'Get document chunks',
        'description'  => 'Fetch a document and its text chunks by numeric document ID.',
        'params'       => [
            'document_id' => 'The numeric ID of the document to retrieve (required).',
        ],
    ],
    'dbn.citation_graph' => [
        'display_name' => 'Explore citation graph',
        'description'  => 'Explore cites, cited-by, implementation, or chain relationships.',
        'params'       => [
            'doc_id' => 'The numeric ID of the document to explore (required).',
            'action' => 'Relationship to traverse: cites, cited_by, implements, or chain (full citation path).',
            'depth'  => 'How many levels of relationships to explore (1–3, default 1).',
        ],
    ],
    'dbn.case_workbench_plan' => [
        'display_name' => 'Plan next case step',
        'description'  => 'Create a stateless legal preparation plan based on your situation.',
        'params'       => [
            'situation' => 'Describe your current legal situation and what you need help with (required).',
            'goal'      => 'Your desired outcome or legal goal.',
            'deadline'  => 'Any relevant deadline (date or description, e.g. "3 weeks").',
            'language'  => 'Response language: en, no, uk, pl, or auto.',
        ],
    ],
    'dbn.save_to_case' => [
        'display_name' => 'Save result to My Case',
        'description'  => 'Explicitly save a prior MCP tool result to the user case record.',
        'params'       => [
            'tool'           => 'The MCP tool slug whose result you are saving (required).',
            'title'          => 'A descriptive title for this saved result.',
            'input_payload'  => 'The input parameters used to generate the result (required).',
            'output_payload' => 'The tool result to save (required).',
            'meta'           => 'Optional metadata (e.g. notes, tags, source reference).',
        ],
    ],
];

echo "\n=== Part 2: Translating MCP tool content ===\n";

// Flatten all tool strings for translation (display_name, description, params)
// Key format: {short_slug}__name, {short_slug}__desc, {short_slug}__p__{param}
$flatSource = [];
$slugMap = [];  // short_slug => full_slug

foreach ($toolsEn as $fullSlug => $toolData) {
    $shortSlug = str_replace('dbn.', '', $fullSlug);
    $slugMap[$shortSlug] = $fullSlug;
    $flatSource[$shortSlug . '__name'] = $toolData['display_name'];
    $flatSource[$shortSlug . '__desc'] = $toolData['description'];
    foreach ($toolData['params'] as $param => $desc) {
        $flatSource[$shortSlug . '__p__' . $param] = $desc;
    }
}

// Translate in batches of 20
$flatKeys    = array_keys($flatSource);
$batches     = array_chunk($flatKeys, 20);
$flatTranslations = ['en' => $flatSource];

foreach ($languages as $langCode => $langName) {
    echo "  Language: $langName ($langCode)\n";
    $langResult = [];
    foreach ($batches as $idx => $batchKeys) {
        $batchNum = $idx + 1;
        echo "    Batch $batchNum/" . count($batches) . " (" . count($batchKeys) . " strings)...\n";
        $batchInput = [];
        foreach ($batchKeys as $k) $batchInput[$k] = $flatSource[$k];
        $langResult = array_merge($langResult, translateBatch($azConfig, $langName, $systemPrompt, $batchInput));
    }
    $flatTranslations[$langCode] = $langResult;
}

// Reconstruct nested structure: [full_slug][lang] => ['display_name', 'description', 'params']
$toolTranslations = [];
foreach ($toolsEn as $fullSlug => $toolData) {
    $shortSlug = str_replace('dbn.', '', $fullSlug);
    foreach (['en', 'no', 'uk', 'pl'] as $lc) {
        $toolTranslations[$fullSlug][$lc] = [
            'display_name' => $flatTranslations[$lc][$shortSlug . '__name'] ?? $toolData['display_name'],
            'description'  => $flatTranslations[$lc][$shortSlug . '__desc'] ?? $toolData['description'],
            'params'       => [],
        ];
        foreach (array_keys($toolData['params']) as $param) {
            $toolTranslations[$fullSlug][$lc]['params'][$param] =
                $flatTranslations[$lc][$shortSlug . '__p__' . $param] ?? $toolData['params'][$param];
        }
    }
}

$toolOutPath = dirname(__DIR__) . '/includes/mcp-tool-translations.php';
writePhpFile($toolOutPath, $toolTranslations, 'MCP tool translations — display_name, description, param descriptions');
echo "  Written: $toolOutPath\n";

echo "\n✓ Done. Next steps:\n";
echo "  1. Copy translations from translations/mcp-chrome.php into includes/i18n.php\n";
echo "  2. The tool translations are ready in includes/mcp-tool-translations.php\n";
