<?php

declare(strict_types=1);

ini_set('display_errors', '0');

header('Content-Type: application/json');

require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../config/config.php';
require_once __DIR__ . '/../ai/form_generator_retry.php';
require_once __DIR__ . '/../ai/prompt_variant_review.php';
require_once __DIR__ . '/../ai/prompt_variant_repair.php';

/**
 * @return never
 */
function variantRepairJsonResponse(array $payload, int $httpCode = 200): void
{
    http_response_code($httpCode);
    echo json_encode($payload, JSON_UNESCAPED_UNICODE);
    exit;
}

$questionId = trim((string) ($_POST['question_id'] ?? ''));
$sourceJson = (string) ($_POST['source_question_json'] ?? '');
$reviewJson = (string) ($_POST['advisory_review_json'] ?? '');

if ($questionId === '') {
    variantRepairJsonResponse([
        'ok' => false,
        'repair_applied' => false,
        'change_log' => [],
        'question' => null,
        'error' => 'missing_question_id',
        'repair_error' => 'Automatic repair unavailable. Variant remains Draft and tutor review is still required.',
        'detail' => 'Missing variant question ID.',
    ], 400);
}

if ($sourceJson === '') {
    variantRepairJsonResponse([
        'ok' => false,
        'repair_applied' => false,
        'change_log' => [],
        'question' => null,
        'error' => 'missing_source',
        'repair_error' => 'Automatic repair unavailable. Variant remains Draft and tutor review is still required.',
        'detail' => 'Missing source question payload.',
    ], 400);
}

$sourceQuestion = json_decode($sourceJson, true);
if (!is_array($sourceQuestion)) {
    variantRepairJsonResponse([
        'ok' => false,
        'repair_applied' => false,
        'change_log' => [],
        'question' => null,
        'error' => 'invalid_source_json',
        'repair_error' => 'Automatic repair unavailable. Variant remains Draft and tutor review is still required.',
        'detail' => 'Source question JSON is invalid.',
    ], 400);
}

$advisoryReview = json_decode($reviewJson, true);
if (!is_array($advisoryReview)) {
    variantRepairJsonResponse([
        'ok' => false,
        'repair_applied' => false,
        'change_log' => [],
        'question' => null,
        'error' => 'invalid_review_json',
        'repair_error' => 'Automatic repair unavailable. Variant remains Draft and tutor review is still required.',
        'detail' => 'Advisory review JSON is invalid.',
    ], 400);
}

$sql = 'SELECT * FROM questions WHERE id = :question_id LIMIT 1';
$stmt = $pdo->prepare($sql);
$stmt->execute(['question_id' => $questionId]);
$variant = $stmt->fetch(PDO::FETCH_ASSOC);

if (!$variant) {
    variantRepairJsonResponse([
        'ok' => false,
        'repair_applied' => false,
        'change_log' => [],
        'question' => null,
        'error' => 'variant_not_found',
        'repair_error' => 'Automatic repair unavailable. Variant remains Draft and tutor review is still required.',
        'detail' => 'Variant question not found.',
    ], 404);
}

if (($variant['source_type'] ?? '') !== 'variant') {
    variantRepairJsonResponse([
        'ok' => false,
        'repair_applied' => false,
        'change_log' => [],
        'question' => null,
        'error' => 'not_variant',
        'repair_error' => 'Automatic repair unavailable. Variant remains Draft and tutor review is still required.',
        'detail' => 'Question is not a generated variant.',
    ], 400);
}

if (($variant['status'] ?? '') !== 'Draft') {
    variantRepairJsonResponse([
        'ok' => false,
        'repair_applied' => false,
        'change_log' => [],
        'question' => null,
        'error' => 'not_draft',
        'repair_error' => 'Automatic repair unavailable. Variant remains Draft and tutor review is still required.',
        'detail' => 'Only Draft variants can be auto-repaired.',
    ], 400);
}

$originalSnapshot = variantQuestionRowToRepairSnapshot($variant);

try {
    if (!variantShouldRunRepair($advisoryReview)) {
        variantRepairJsonResponse([
            'ok' => true,
            'repair_applied' => false,
            'change_log' => [],
            'question' => variantRepairContentToApiQuestion($originalSnapshot, $variant),
            'error' => '',
            'repair_error' => '',
            'detail' => 'no_repair_needed',
        ]);
    }

    $prompt = buildVariantRepairPrompt($sourceQuestion, $variant, $advisoryReview);
    $fetch = formGeneratorOpenAiChatJsonQuestion(
        $prompt,
        '',
        0,
        0.2,
        variantOpenAiRepairModel()
    );

    if (!$fetch['ok'] || !is_array($fetch['data'])) {
        $detail = $fetch['error'] !== '' ? $fetch['error'] : 'Repair service could not complete.';
        error_log('[repair_variant_from_review] OpenAI failure question_id=' . $questionId . ' ' . $detail);
        variantRepairJsonResponse([
            'ok' => false,
            'repair_applied' => false,
            'change_log' => [],
            'question' => variantRepairContentToApiQuestion($originalSnapshot, $variant),
            'error' => 'openai_failed',
            'repair_error' => 'Automatic repair unavailable. Variant remains Draft and tutor review is still required.',
            'detail' => $detail,
        ], 502);
    }

    $normalized = normalizeVariantRepairResponse($fetch['data'], $originalSnapshot);
    if (!$normalized['ok'] || !is_array($normalized['data'])) {
        error_log('[repair_variant_from_review] Invalid repair JSON question_id=' . $questionId . ' '
            . ($normalized['error'] ?? ''));
        variantRepairJsonResponse([
            'ok' => false,
            'repair_applied' => false,
            'change_log' => [],
            'question' => variantRepairContentToApiQuestion($originalSnapshot, $variant),
            'error' => 'invalid_repair_json',
            'repair_error' => 'Automatic repair unavailable. Variant remains Draft and tutor review is still required.',
            'detail' => $normalized['error'] !== '' ? $normalized['error'] : 'Repair JSON could not be validated.',
        ], 502);
    }

    $repairData = $normalized['data'];

    if (!empty($repairData['repair_blocked'])) {
        variantRepairJsonResponse([
            'ok' => true,
            'repair_applied' => false,
            'repair_blocked' => true,
            'change_log' => [],
            'question' => variantRepairContentToApiQuestion($originalSnapshot, $variant),
            'error' => '',
            'repair_error' => '',
            'detail' => 'repair_blocked',
        ]);
    }

    if (!empty($repairData['no_changes_needed'])) {
        variantRepairJsonResponse([
            'ok' => true,
            'repair_applied' => false,
            'change_log' => [],
            'question' => variantRepairContentToApiQuestion($originalSnapshot, $variant),
            'error' => '',
            'repair_error' => '',
            'detail' => 'no_changes',
        ]);
    }

    $repaired = $repairData['repaired_question'] ?? null;
    if (!is_array($repaired)) {
        variantRepairJsonResponse([
            'ok' => false,
            'repair_applied' => false,
            'change_log' => [],
            'question' => variantRepairContentToApiQuestion($originalSnapshot, $variant),
            'error' => 'missing_repaired_question',
            'repair_error' => 'Automatic repair unavailable. Variant remains Draft and tutor review is still required.',
            'detail' => 'Repair did not return question content.',
        ], 502);
    }

    $apply = variantApplyRepairToDraftVariant($pdo, $questionId, $repaired);
    if (!$apply['ok']) {
        error_log('[repair_variant_from_review] DB update failed question_id=' . $questionId . ' ' . $apply['error']);
        variantRepairJsonResponse([
            'ok' => false,
            'repair_applied' => false,
            'change_log' => [],
            'question' => variantRepairContentToApiQuestion($originalSnapshot, $variant),
            'error' => 'db_update_failed',
            'repair_error' => 'Automatic repair unavailable. Variant remains Draft and tutor review is still required.',
            'detail' => $apply['error'],
        ], 500);
    }

    $stmt = $pdo->prepare('SELECT * FROM questions WHERE id = :question_id LIMIT 1');
    $stmt->execute(['question_id' => $questionId]);
    $updatedRow = $stmt->fetch(PDO::FETCH_ASSOC);
    if (!$updatedRow) {
        variantRepairJsonResponse([
            'ok' => false,
            'repair_applied' => false,
            'change_log' => [],
            'question' => variantRepairContentToApiQuestion($originalSnapshot, $variant),
            'error' => 'reload_failed',
            'repair_error' => 'Automatic repair unavailable. Variant remains Draft and tutor review is still required.',
            'detail' => 'Could not reload variant after repair.',
        ], 500);
    }

    $changeLog = is_array($repairData['change_log'] ?? null) ? $repairData['change_log'] : [];

    variantRepairJsonResponse([
        'ok' => true,
        'repair_applied' => true,
        'repair_blocked' => false,
        'change_log' => $changeLog,
        'question' => variantRepairContentToApiQuestion(
            variantQuestionRowToRepairSnapshot($updatedRow),
            $updatedRow
        ),
        'error' => '',
        'repair_error' => '',
        'detail' => '',
    ]);
} catch (Throwable $e) {
    error_log('[repair_variant_from_review] Exception question_id=' . $questionId . ' ' . $e->getMessage());
    variantRepairJsonResponse([
        'ok' => false,
        'repair_applied' => false,
        'change_log' => [],
        'question' => variantRepairContentToApiQuestion($originalSnapshot, $variant),
        'error' => 'exception',
        'repair_error' => 'Automatic repair unavailable. Variant remains Draft and tutor review is still required.',
        'detail' => 'An unexpected error occurred.',
    ], 500);
}
