<?php

/**
 * Normalize tickets.journeydata to passenger boarding day for overnight pickups.
 *
 * Run after backfill_journeylists_service_dates.php so journeylists.journeydate is the bus run day.
 *
 * Usage (from project root):
 *   php database/scripts/fix_legacy_overnight_ticket_journeydata.php --dry-run
 *   php database/scripts/fix_legacy_overnight_ticket_journeydata.php --apply
 *   php database/scripts/fix_legacy_overnight_ticket_journeydata.php --apply --trip=61
 */

declare(strict_types=1);

$dryRun = in_array('--dry-run', $argv ?? [], true) || ! in_array('--apply', $argv ?? [], true);
$tripFilter = null;
foreach ($argv ?? [] as $arg) {
    if (str_starts_with($arg, '--trip=')) {
        $tripFilter = (int) substr($arg, 7);
    }
}

define('FCPATH', dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR);

require dirname(__DIR__, 2) . '/vendor/autoload.php';

$pathsConfig = new Config\Paths();
require rtrim($pathsConfig->systemDirectory, '\\/ ') . '/bootstrap.php';

$app = Config\Services::codeigniter();
$app->initialize();

$db     = \Config\Database::connect();
$helper = new \App\Libraries\TripJourneyDateHelper();

\App\Libraries\BookingInventorySupport::syncBookingTimezone();

$sql = 'SELECT t.id, t.booking_id, t.trip_id, t.subtrip_id, t.pick_stand_id, t.journeydata,
               MIN(DATE(jl.journeydate)) AS manifest_day
        FROM tickets t
        INNER JOIN journeylists jl ON jl.booking_id = t.booking_id AND jl.trip_id = t.trip_id AND jl.deleted_at IS NULL
        WHERE t.deleted_at IS NULL AND t.cancel_status = 0 AND t.refund = 0';
$params = [];
if ($tripFilter > 0) {
    $sql .= ' AND t.trip_id = ?';
    $params[] = $tripFilter;
}
$sql .= ' GROUP BY t.id, t.booking_id, t.trip_id, t.subtrip_id, t.pick_stand_id, t.journeydata
          ORDER BY t.id ASC';

$rows = $db->query($sql, $params)->getResult();

$wouldUpdate = 0;
$updated     = 0;
$skipped     = 0;

foreach ($rows as $row) {
    $tripId      = (int) ($row->trip_id ?? 0);
    $subtripId   = (int) ($row->subtrip_id ?? 0);
    $pickStandId = (int) ($row->pick_stand_id ?? 0);
    $storedDay   = \App\Libraries\BookingInventorySupport::normalizeCalendarDate((string) ($row->journeydata ?? ''));
    $manifestDay = \App\Libraries\BookingInventorySupport::normalizeCalendarDate((string) ($row->manifest_day ?? ''));

    if ($tripId <= 0 || $subtripId <= 0 || $pickStandId <= 0 || $storedDay === '1970-01-01' || $manifestDay === '1970-01-01') {
        $skipped++;
        continue;
    }

    $expectedBoarding = $helper->getBoardingDateFromBusStartDate($tripId, $subtripId, $manifestDay, $pickStandId);
    if ($expectedBoarding === '1970-01-01' || $expectedBoarding === $manifestDay) {
        $skipped++;
        continue;
    }

    if ($storedDay === $expectedBoarding) {
        continue;
    }

    $targetDay = $expectedBoarding;
    if ($storedDay === $manifestDay) {
        $targetDay = $expectedBoarding;
    } elseif ($storedDay === date('Y-m-d', strtotime($expectedBoarding . ' +1 day'))) {
        $targetDay = $expectedBoarding;
    } else {
        $skipped++;
        continue;
    }

    $wouldUpdate++;
    echo sprintf(
        "%s booking=%s trip=%d pick=%d manifest=%s journeydata %s -> %s\n",
        $dryRun ? '[dry-run]' : '[apply]',
        (string) $row->booking_id,
        $tripId,
        $pickStandId,
        $manifestDay,
        $storedDay,
        $targetDay
    );

    if (! $dryRun) {
        $db->query(
            'UPDATE tickets SET journeydata = ? WHERE id = ?',
            [$targetDay . ' 00:00:00', (int) $row->id]
        );
        $updated++;
    }
}

echo PHP_EOL . sprintf(
    "Done. candidates=%d %s=%d skipped=%d\n",
    $wouldUpdate,
    $dryRun ? 'would_update' : 'updated',
    $dryRun ? $wouldUpdate : $updated,
    $skipped
);

if ($dryRun) {
    echo "Re-run with --apply to persist changes.\n";
}
