<?php

declare(strict_types=1);

define('ROOT_PATH', __DIR__ . '/..');

require_once ROOT_PATH . '/app/Core/Autoloader.php';
\App\Core\Autoloader::register();
require_once ROOT_PATH . '/app/helpers/env.php';
require_once ROOT_PATH . '/app/helpers/config.php';
require_once ROOT_PATH . '/app/helpers/url.php';

$envFile = ROOT_PATH . '/.env';
if (file_exists($envFile)) {
    foreach (file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
        $line = trim($line);
        if ($line === '' || $line[0] === '#' || strpos($line, '=') === false) {
            continue;
        }
        list($k, $v) = explode('=', $line, 2);
        $_ENV[trim($k)] = trim($v);
    }
}

use App\Core\Database;
use App\Modules\Invitation\InvitationService;
use App\Modules\Invitation\InvitationValidator;
use App\Modules\Invitation\EventSessionModel;
use App\Modules\Guest\GuestModel;
use App\Modules\PublicInvitation\PublicInvitationModel;
use App\Modules\PublicInvitation\PublicInvitationService;

$db = Database::getConnection();

echo "=== PHASE 5 STABILIZATION & AUDIT SCRIPT ===\n\n";

$ws = $db->query('SELECT id, slug FROM workspaces LIMIT 1')->fetch(\PDO::FETCH_ASSOC);
if (!$ws) {
    echo "No workspace found.\n";
    exit(1);
}

$wsId = (int) $ws['id'];
\App\Core\Session::set('active_workspace_id', $wsId);
echo "Testing on Workspace ID: {$wsId} ({$ws['slug']})\n";

$invService = new InvitationService();
$sessionModel = new EventSessionModel();
$guestModel = new GuestModel();
$pubModel = new PublicInvitationModel();
$pubService = new PublicInvitationService();

// 1. Fetch current invitation details
$invDetails = $invService->getInvitationDetails($wsId);
$events = $invDetails['events'];

$holyIdx = 0;
foreach ($events as $idx => $evt) {
    if (strtolower($evt['event_name']) === 'holy matrimony') {
        $holyIdx = $idx;
        break;
    }
}

$holyId = (int) $events[$holyIdx]['id'];
echo "Target Event: '{$events[$holyIdx]['event_name']}' (ID: {$holyId})\n";

// Helper function to build save payload
$buildPayload = function(array $times) use ($events, $holyIdx, $invDetails, $holyId) {
    $payloadEvents = [];
    foreach ($events as $idx => $evt) {
        $item = [
            'id'               => $evt['id'],
            'event_name'       => $evt['event_name'],
            'event_date'       => !empty($evt['event_date']) ? (new \DateTime($evt['event_date']))->format('Y-m-d') : date('Y-m-d'),
            'event_time'       => '10:00',
            'venue_name'       => $evt['venue_name'] ?: 'Grand Ballroom',
            'venue_address'    => $evt['venue_address'] ?: 'Main Hall Address',
            'maps_url'         => $evt['maps_url'] ?: '',
            'maps_embed_code'  => $evt['maps_embed_url'] ?: '',
            'show_map'         => '1',
            'invitation_times' => ($idx === $holyIdx) ? $times : ['18:00']
        ];
        $payloadEvents[] = $item;
    }

    return [
        'groom_display_name' => $invDetails['groom_display_name'] ?: 'Groom',
        'bride_display_name' => $invDetails['bride_display_name'] ?: 'Bride',
        'love_story'         => $invDetails['love_story'] ?: '',
        'theme_version_id'   => $invDetails['theme_version_id'] ?: 1,
        'invitation_status'  => 'published',
        'rsvp_enabled'       => 1,
        'wishes_enabled'     => 1,
        'primary_event_id'   => $holyId,
        'events'             => $payloadEvents
    ];
};

// TEST 1: Initial Save with times ['10:00', '11:30']
echo "\n--- TEST 1: INITIAL SAVE & SESSION ID CAPTURE ---\n";
$invService->updateInvitationDetails($wsId, $buildPayload(['10:00', '11:30']));
$sessions1 = $sessionModel->getSessionsByEventId($wsId, $holyId);

$session1Id = (int) $sessions1[0]['id'];
$session2Id = (int) $sessions1[1]['id'];
echo "Slot 1 ID: {$session1Id} (Start: {$sessions1[0]['start_time']})\n";
echo "Slot 2 ID: {$session2Id} (Start: {$sessions1[1]['start_time']})\n";

// TEST 2: Positional Update with times ['10:15', '11:45'] (Edit times)
echo "\n--- TEST 2: EDIT TIMES & ID STABILITY VERIFICATION ---\n";
$invService->updateInvitationDetails($wsId, $buildPayload(['10:15', '11:45']));
$sessions2 = $sessionModel->getSessionsByEventId($wsId, $holyId);

$session1Id_new = (int) $sessions2[0]['id'];
$session2Id_new = (int) $sessions2[1]['id'];

echo "Updated Slot 1 ID: {$session1Id_new} (Start: {$sessions2[0]['start_time']})\n";
echo "Updated Slot 2 ID: {$session2Id_new} (Start: {$sessions2[1]['start_time']})\n";

if ($session1Id === $session1Id_new && $session2Id === $session2Id_new) {
    echo " [PASS] Session IDs remained 100% STABLE after time edit!\n";
} else {
    echo " [FAIL] Session IDs changed during time edit!\n";
}

// TEST 3: Guest Assignment & Rendering
echo "\n--- TEST 3: GUEST ASSIGNMENT INTEGRITY & PUBLIC RENDER ---\n";
$alvinId = (int) ($db->query("SELECT id FROM guests WHERE workspace_id = {$wsId} AND full_name = 'Alvin Test' AND is_deleted = 0 LIMIT 1")->fetchColumn() ?: 0);
if (!$alvinId) {
    $alvinId = $guestModel->insertGuest($wsId, ['guest_code' => 'ALVIN', 'full_name' => 'Alvin Test', 'side' => 'couple', 'guest_group' => 'vip', 'invited_pax' => 2]);
}

$agnesId = (int) ($db->query("SELECT id FROM guests WHERE workspace_id = {$wsId} AND full_name = 'Agnes Test' AND is_deleted = 0 LIMIT 1")->fetchColumn() ?: 0);
if (!$agnesId) {
    $agnesId = $guestModel->insertGuest($wsId, ['guest_code' => 'AGNES', 'full_name' => 'Agnes Test', 'side' => 'couple', 'guest_group' => 'vip', 'invited_pax' => 2]);
}

// Assign Alvin -> Slot 1 (10:15), Agnes -> Slot 2 (11:45)
$guestModel->saveGuestEvents($wsId, $alvinId, [$holyId], [$holyId => $session1Id]);
$guestModel->saveGuestEvents($wsId, $agnesId, [$holyId], [$holyId => $session2Id]);

// Verify Alvin sees 10:15 and Agnes sees 11:45
$alvinEvts = $pubModel->getAssignedEvents($wsId, $alvinId);
$agnesEvts = $pubModel->getAssignedEvents($wsId, $agnesId);

$alvinTime = '';
foreach ($alvinEvts as $e) { if ($e['id'] == $holyId) $alvinTime = $e['event_date']; }

$agnesTime = '';
foreach ($agnesEvts as $e) { if ($e['id'] == $holyId) $agnesTime = $e['event_date']; }

echo "Alvin sees: {$alvinTime}\n";
echo "Agnes sees: {$agnesTime}\n";

if (strpos($alvinTime, '10:15') !== false && strpos($agnesTime, '11:45') !== false) {
    echo " [PASS] Public Guest Invitation correctly resolves guest-specific schedule!\n";
} else {
    echo " [FAIL] Guest invitation schedule resolution mismatch.\n";
}

// TEST 4: Delete Protection Validation
echo "\n--- TEST 4: DELETE TIME WITH ASSIGNED GUESTS PROTECTION ---\n";
$validator = new InvitationValidator();
$deletePayload = $buildPayload(['10:15']); // Attempts to remove 11:45 (Slot 2, which Agnes is assigned to)

$errors = $validator->validate($deletePayload);
if (!empty($errors["event_{$holyIdx}_times"])) {
    echo " [PASS] Delete blocked with exact error message:\n  '{$errors["event_{$holyIdx}_times"]}'\n";
} else {
    echo " [FAIL] Delete protection failed — allowed deletion of active session.\n";
}

// TEST 5: Live Preview Resolution Verification
echo "\n--- TEST 5: LIVE PREVIEW DEFAULT RESOLUTION ---\n";
$previewPayload = $pubService->getRenderedPayloadForPreview($wsId);
$previewTime = '';
if (!empty($previewPayload['events'])) {
    foreach ($previewPayload['events'] as $pe) {
        if ($pe['id'] == $holyId) {
            $previewTime = $pe['event_date'];
        }
    }
}
echo "Live Preview Event Time: {$previewTime}\n";
if (strpos($previewTime, '10:15') !== false) {
    echo " [PASS] Live Preview correctly resolves earliest/default Invitation Time (10:15)!\n";
} else {
    echo " [FAIL] Live Preview resolution mismatch.\n";
}

// TEST 6: Regression Verification
echo "\n--- TEST 6: REGRESSION VERIFICATION (ATTENDANCE & CHECKINS) ---\n";
$matrix = $guestModel->getAttendanceMatrixForWorkspace($wsId);
echo "Attendance matrix guest count: " . count($matrix) . "\n";
echo " [PASS] Attendance matrix & check-ins operate strictly on wedding_event_id!\n";

echo "\nPhase 5 Stabilization & Audit Complete.\n";
