<?php

declare(strict_types=1);

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

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

    return trim($value);
}

function m3_email_norm(?string $email): ?string
{
    $normalized = strtolower(trim((string)$email));

    return $normalized !== '' ? $normalized : null;
}

function m3_decimal_to_cents(mixed $value): int
{
    $normalized = str_replace(',', '.', trim((string)$value));
    if ($normalized === '') {
        return 0;
    }

    $negative = str_starts_with($normalized, '-');
    if ($negative) {
        $normalized = substr($normalized, 1);
    }

    [$euros, $cents] = array_pad(explode('.', $normalized, 2), 2, '0');
    $euros = preg_replace('/[^0-9]/', '', $euros) ?? '0';
    $cents = preg_replace('/[^0-9]/', '', $cents) ?? '0';
    $cents = str_pad(substr($cents, 0, 2), 2, '0');

    $result = ((int)$euros * 100) + (int)$cents;

    return $negative ? -$result : $result;
}

function m3_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 created.");
    }

    return (int)$tenantId;
}

function m3_upsert_user(PDO $pdo, string $email, string $emailNorm, string $displayName): int
{
    $stmt = $pdo->prepare(
        'INSERT INTO users (email, email_norm, display_name, status)
         VALUES (?, ?, ?, ?)
         ON DUPLICATE KEY UPDATE
           email = VALUES(email),
           display_name = VALUES(display_name),
           status = VALUES(status)'
    );
    $stmt->execute([$email, $emailNorm, $displayName, 'active']);

    $stmt = $pdo->prepare('SELECT id FROM users WHERE email_norm = ?');
    $stmt->execute([$emailNorm]);
    $userId = $stmt->fetchColumn();

    if ($userId === false) {
        throw new RuntimeException("User '{$emailNorm}' was not created.");
    }

    return (int)$userId;
}

$pdo = dev_pdo();
$applied = dev_apply_migrations($pdo);

$tenantSlug = m3_env('M3_DEFAULT_TENANT_SLUG', 'default');
$tenantName = m3_env('M3_DEFAULT_TENANT_NAME', 'Kaffeeliste Bestand');
$ownerEmailNorm = m3_email_norm(getenv('M3_DEFAULT_TENANT_OWNER_EMAIL') ?: null);

$stats = [
    'applied_migrations' => count($applied),
    'participants' => 0,
    'stale_participants_removed' => 0,
    'users' => 0,
    'memberships' => 0,
];

$pdo->beginTransaction();

try {
    $stmt = $pdo->prepare(
        'INSERT INTO tenants (slug, name, status, timezone, locale, currency_code)
         VALUES (?, ?, ?, ?, ?, ?)
         ON DUPLICATE KEY UPDATE
           name = VALUES(name),
           status = VALUES(status),
           timezone = VALUES(timezone),
           locale = VALUES(locale),
           currency_code = VALUES(currency_code)'
    );
    $stmt->execute([$tenantSlug, $tenantName, 'active', 'Europe/Berlin', 'de-DE', 'EUR']);
    $tenantId = m3_fetch_tenant_id($pdo, $tenantSlug);

    $config = $pdo->query(
        'SELECT KostenproStrich, paypaluse, paypallink, strichperweb
         FROM kl_config
         ORDER BY id
         LIMIT 1'
    )->fetch() ?: [
        'KostenproStrich' => '0.20',
        'paypaluse' => 0,
        'paypallink' => '',
        'strichperweb' => 1,
    ];

    $stmt = $pdo->prepare(
        'INSERT INTO tenant_settings
           (tenant_id, mark_price_cents, self_entry_enabled, paypal_enabled, paypal_url_template)
         VALUES (?, ?, ?, ?, ?)
         ON DUPLICATE KEY UPDATE
           mark_price_cents = VALUES(mark_price_cents),
           self_entry_enabled = VALUES(self_entry_enabled),
           paypal_enabled = VALUES(paypal_enabled),
           paypal_url_template = VALUES(paypal_url_template)'
    );
    $stmt->execute([
        $tenantId,
        m3_decimal_to_cents($config['KostenproStrich']),
        (int)$config['strichperweb'] === 1 ? 1 : 0,
        (int)$config['paypaluse'] === 1 ? 1 : 0,
        (string)$config['paypallink'],
    ]);

    $members = $pdo->query(
        'SELECT MitarbeiterID, Name, Email, paypalname, aktiv, admin
         FROM kl_Mitarbeiter
         ORDER BY MitarbeiterID'
    )->fetchAll();

    $upsertParticipant = $pdo->prepare(
        'INSERT INTO participants
           (tenant_id, display_name, email, email_norm, paypal_name, active, legacy_mitarbeiter_id)
         VALUES (?, ?, ?, ?, ?, ?, ?)
         ON DUPLICATE KEY UPDATE
           display_name = VALUES(display_name),
           email = VALUES(email),
           email_norm = VALUES(email_norm),
           paypal_name = VALUES(paypal_name),
           active = VALUES(active),
           legacy_mitarbeiter_id = VALUES(legacy_mitarbeiter_id)'
    );
    $upsertMembership = $pdo->prepare(
        'INSERT INTO tenant_memberships (tenant_id, user_id, role, status, joined_at)
         VALUES (?, ?, ?, ?, NOW())
         ON DUPLICATE KEY UPDATE
           role = VALUES(role),
           status = VALUES(status),
           joined_at = COALESCE(tenant_memberships.joined_at, VALUES(joined_at))'
    );
    $linkParticipantUser = $pdo->prepare(
        'UPDATE participants
         SET user_id = ?
         WHERE tenant_id = ?
           AND legacy_mitarbeiter_id = ?'
    );

    foreach ($members as $member) {
        $email = trim((string)$member['Email']);
        $emailNorm = m3_email_norm($email);
        $displayName = trim((string)$member['Name']);
        if ($displayName === '') {
            $displayName = $emailNorm ?? ('Mitarbeiter ' . (int)$member['MitarbeiterID']);
        }

        $upsertParticipant->execute([
            $tenantId,
            $displayName,
            $email !== '' ? $email : null,
            $emailNorm,
            $member['paypalname'] !== null && trim((string)$member['paypalname']) !== ''
                ? trim((string)$member['paypalname'])
                : null,
            (int)$member['aktiv'] === 1 ? 1 : 0,
            (int)$member['MitarbeiterID'],
        ]);
        $stats['participants']++;

        $isAdmin = (int)$member['admin'] === 1 && (int)$member['aktiv'] === 1;
        $isOwner = $ownerEmailNorm !== null && $emailNorm === $ownerEmailNorm && (int)$member['aktiv'] === 1;
        if ($emailNorm === null || (!$isAdmin && !$isOwner)) {
            continue;
        }

        $userId = m3_upsert_user($pdo, $email, $emailNorm, $displayName);
        $role = $isOwner ? 'owner' : 'admin';
        $upsertMembership->execute([$tenantId, $userId, $role, 'active']);
        $linkParticipantUser->execute([$userId, $tenantId, (int)$member['MitarbeiterID']]);
        $stats['users']++;
        $stats['memberships']++;
    }

    $removeStaleParticipants = $pdo->prepare(
        'DELETE p
         FROM participants p
         LEFT JOIN kl_Mitarbeiter m
           ON m.MitarbeiterID = p.legacy_mitarbeiter_id
         WHERE p.tenant_id = ?
           AND p.legacy_mitarbeiter_id IS NOT NULL
           AND m.MitarbeiterID IS NULL'
    );
    $removeStaleParticipants->execute([$tenantId]);
    $stats['stale_participants_removed'] = $removeStaleParticipants->rowCount();

    $pdo->commit();
} catch (Throwable $e) {
    $pdo->rollBack();
    fwrite(STDERR, "M3 default tenant backfill failed: {$e->getMessage()}\n");
    exit(1);
}

echo "M3 default tenant backfill complete.\n";
echo "Tenant: {$tenantSlug}\n";
echo "Applied migrations: {$stats['applied_migrations']}\n";
echo "Participants mirrored: {$stats['participants']}\n";
echo "Stale participants removed: {$stats['stale_participants_removed']}\n";
echo "Users upserted: {$stats['users']}\n";
echo "Memberships upserted: {$stats['memberships']}\n";
