<?php

declare(strict_types=1);

require __DIR__ . '/dev-db.php';

function m4_env(string $name, string $default): string
{
    $value = getenv($name);
    if ($value === false || trim($value) === '') {
        return $default;
    }

    return trim($value);
}

function m4_fetch_tenant_id(PDO $pdo, string $slug): int
{
    $stmt = $pdo->prepare('SELECT id FROM tenants WHERE slug = ?');
    $stmt->execute([$slug]);
    $tenantId = $stmt->fetchColumn();

    if ($tenantId === false) {
        throw new RuntimeException("Tenant '{$slug}' was not found. Run scripts/backfill-default-tenant.php first.");
    }

    return (int)$tenantId;
}

function m4_count_missing_payment_participants(PDO $pdo, int $tenantId): int
{
    $stmt = $pdo->prepare(
        'SELECT COUNT(*)
         FROM kl_Einzahlungen e
         LEFT JOIN participants p
           ON p.tenant_id = ?
          AND p.legacy_mitarbeiter_id = e.MitarbeiterID
         WHERE p.id IS NULL'
    );
    $stmt->execute([$tenantId]);

    return (int)$stmt->fetchColumn();
}

function m4_count_missing_consumption_participants(PDO $pdo, int $tenantId): int
{
    $stmt = $pdo->prepare(
        'SELECT COUNT(*)
         FROM kl_Kaffeeverbrauch v
         LEFT JOIN participants p
           ON p.tenant_id = ?
          AND p.legacy_mitarbeiter_id = v.MitarbeiterID
         WHERE p.id IS NULL'
    );
    $stmt->execute([$tenantId]);

    return (int)$stmt->fetchColumn();
}

$pdo = dev_pdo();
$applied = dev_apply_migrations($pdo);
$tenantSlug = m4_env('M4_DEFAULT_TENANT_SLUG', m4_env('M3_DEFAULT_TENANT_SLUG', 'default'));

$stats = [
    'applied_migrations' => count($applied),
    'stale_payments_removed' => 0,
    'stale_consumptions_removed' => 0,
    'payments_mirrored' => 0,
    'consumptions_mirrored' => 0,
];

try {
    $tenantId = m4_fetch_tenant_id($pdo, $tenantSlug);
    $missingPayments = m4_count_missing_payment_participants($pdo, $tenantId);
    $missingConsumptions = m4_count_missing_consumption_participants($pdo, $tenantId);
    if ($missingPayments > 0 || $missingConsumptions > 0) {
        throw new RuntimeException(
            "Missing participant mappings for {$missingPayments} payment(s) and {$missingConsumptions} consumption(s)."
        );
    }

    $pdo->beginTransaction();

    $removeStalePayments = $pdo->prepare(
        "DELETE le
         FROM ledger_entries le
         LEFT JOIN kl_Einzahlungen e
           ON e.EinzahlungsID = le.legacy_id
         WHERE le.tenant_id = ?
           AND le.legacy_table = 'kl_Einzahlungen'
           AND e.EinzahlungsID IS NULL"
    );
    $removeStalePayments->execute([$tenantId]);
    $stats['stale_payments_removed'] = $removeStalePayments->rowCount();

    $removeStaleConsumptions = $pdo->prepare(
        "DELETE le
         FROM ledger_entries le
         LEFT JOIN kl_Kaffeeverbrauch v
           ON v.VerbrauchID = le.legacy_id
         WHERE le.tenant_id = ?
           AND le.legacy_table = 'kl_Kaffeeverbrauch'
           AND v.VerbrauchID IS NULL"
    );
    $removeStaleConsumptions->execute([$tenantId]);
    $stats['stale_consumptions_removed'] = $removeStaleConsumptions->rowCount();

    $insertPayments = $pdo->prepare(
        "INSERT INTO ledger_entries
           (tenant_id, participant_id, type, amount_cents, marks_count,
            unit_price_cents, booked_at, source, note, legacy_table, legacy_id)
         SELECT
           p.tenant_id,
           p.id,
           'payment',
           CAST(ROUND(e.Betrag * 100) AS SIGNED),
           NULL,
           NULL,
           e.Datum,
           'legacy_payment',
           NULL,
           'kl_Einzahlungen',
           e.EinzahlungsID
         FROM kl_Einzahlungen e
         JOIN participants p
           ON p.tenant_id = ?
          AND p.legacy_mitarbeiter_id = e.MitarbeiterID
         ON DUPLICATE KEY UPDATE
           participant_id = VALUES(participant_id),
           type = VALUES(type),
           amount_cents = VALUES(amount_cents),
           marks_count = VALUES(marks_count),
           unit_price_cents = VALUES(unit_price_cents),
           booked_at = VALUES(booked_at),
           source = VALUES(source),
           note = VALUES(note)"
    );
    $insertPayments->execute([$tenantId]);

    $insertConsumptions = $pdo->prepare(
        "INSERT INTO ledger_entries
           (tenant_id, participant_id, type, amount_cents, marks_count,
            unit_price_cents, booked_at, source, note, legacy_table, legacy_id)
         SELECT
           p.tenant_id,
           p.id,
           'consumption',
           -CAST(ROUND(v.Kosten * 100) AS SIGNED),
           v.AnzahlStriche,
           CAST(ROUND(v.KostenproStrich * 100) AS SIGNED),
           v.Datum,
           CASE
             WHEN v.Eintragsart = 2 THEN 'legacy_web'
             ELSE 'legacy_manual'
           END,
           CASE
             WHEN v.Eintragsart IS NULL THEN NULL
             ELSE CONCAT('Legacy Eintragsart: ', v.Eintragsart)
           END,
           'kl_Kaffeeverbrauch',
           v.VerbrauchID
         FROM kl_Kaffeeverbrauch v
         JOIN participants p
           ON p.tenant_id = ?
          AND p.legacy_mitarbeiter_id = v.MitarbeiterID
         ON DUPLICATE KEY UPDATE
           participant_id = VALUES(participant_id),
           type = VALUES(type),
           amount_cents = VALUES(amount_cents),
           marks_count = VALUES(marks_count),
           unit_price_cents = VALUES(unit_price_cents),
           booked_at = VALUES(booked_at),
           source = VALUES(source),
           note = VALUES(note)"
    );
    $insertConsumptions->execute([$tenantId]);

    $stmt = $pdo->prepare(
        "SELECT COUNT(*)
         FROM ledger_entries
         WHERE tenant_id = ?
           AND legacy_table = 'kl_Einzahlungen'"
    );
    $stmt->execute([$tenantId]);
    $stats['payments_mirrored'] = (int)$stmt->fetchColumn();

    $stmt = $pdo->prepare(
        "SELECT COUNT(*)
         FROM ledger_entries
         WHERE tenant_id = ?
           AND legacy_table = 'kl_Kaffeeverbrauch'"
    );
    $stmt->execute([$tenantId]);
    $stats['consumptions_mirrored'] = (int)$stmt->fetchColumn();

    $pdo->commit();
} catch (Throwable $e) {
    if ($pdo->inTransaction()) {
        $pdo->rollBack();
    }

    fwrite(STDERR, "M4 ledger backfill failed: {$e->getMessage()}\n");
    exit(1);
}

echo "M4 ledger backfill complete.\n";
echo "Tenant: {$tenantSlug}\n";
echo "Applied migrations: {$stats['applied_migrations']}\n";
echo "Stale payments removed: {$stats['stale_payments_removed']}\n";
echo "Stale consumptions removed: {$stats['stale_consumptions_removed']}\n";
echo "Payments mirrored: {$stats['payments_mirrored']}\n";
echo "Consumptions mirrored: {$stats['consumptions_mirrored']}\n";
