<?php

declare(strict_types=1);

function rib_detect_columns(PDO $pdo): ?array
{
    $table = table_exists($pdo, 'rib') ? 'rib' : null;
    if ($table === null) {
        return null;
    }

    return [
        'table' => $table,
        'id' => pick_column($pdo, $table, ['id'], false),
        'iban' => pick_column($pdo, $table, ['iban', 'rib', 'iban_code'], false),
        'bic' => pick_column($pdo, $table, ['bic', 'swift', 'swift_code'], false),
        'holder' => pick_column($pdo, $table, ['titulaire', 'owner', 'nom', 'nom_titulaire'], false),
        'bank' => pick_column($pdo, $table, ['banque', 'bank', 'bank_name'], false),
        'created_at' => pick_column($pdo, $table, ['created_at', 'date_creation'], false),
        'updated_at' => pick_column($pdo, $table, ['updated_at'], false),
    ];
}

function rib_get(): array
{
    $pdo = db();
    $schema = rib_detect_columns($pdo);
    if ($schema === null) {
        return [
            'iban' => '',
            'bic' => '',
            'holder' => '',
            'bank' => '',
        ];
    }

    $sql = 'SELECT * FROM ' . qi($schema['table']) . ' ';
    if ($schema['id'] !== null) {
        $sql .= 'ORDER BY ' . qi($schema['id']) . ' ASC ';
    }
    $sql .= 'LIMIT 1';

    $stmt = $pdo->query($sql);
    $row = $stmt->fetch();
    if (!is_array($row)) {
        return [
            'iban' => '',
            'bic' => '',
            'holder' => '',
            'bank' => '',
        ];
    }

    return [
        'iban' => $schema['iban'] !== null ? trim((string) ($row[$schema['iban']] ?? '')) : '',
        'bic' => $schema['bic'] !== null ? trim((string) ($row[$schema['bic']] ?? '')) : '',
        'holder' => $schema['holder'] !== null ? trim((string) ($row[$schema['holder']] ?? '')) : '',
        'bank' => $schema['bank'] !== null ? trim((string) ($row[$schema['bank']] ?? '')) : '',
    ];
}

function rib_upsert(array $payload): array
{
    $pdo = db();
    $schema = rib_detect_columns($pdo);
    if ($schema === null) {
        throw new RuntimeException('Table rib introuvable.');
    }

    $iban = trim((string) ($payload['iban'] ?? ''));
    $bic = trim((string) ($payload['bic'] ?? ''));
    $holder = trim((string) ($payload['holder'] ?? ''));
    $bank = trim((string) ($payload['bank'] ?? ''));

    $data = [];
    if ($schema['iban'] !== null) {
        $data[$schema['iban']] = $iban;
    }
    if ($schema['bic'] !== null) {
        $data[$schema['bic']] = $bic;
    }
    if ($schema['holder'] !== null) {
        $data[$schema['holder']] = $holder;
    }
    if ($schema['bank'] !== null) {
        $data[$schema['bank']] = $bank;
    }
    if ($schema['updated_at'] !== null) {
        $data[$schema['updated_at']] = date('Y-m-d H:i:s');
    }

    if ($data === []) {
        throw new RuntimeException('Colonnes RIB non compatibles.');
    }

    $existingId = null;
    if ($schema['id'] !== null) {
        $sql = 'SELECT ' . qi($schema['id']) . ' AS id FROM ' . qi($schema['table']) . ' ORDER BY ' . qi($schema['id']) . ' ASC LIMIT 1';
        $stmt = $pdo->query($sql);
        $row = $stmt->fetch();
        if (is_array($row) && isset($row['id'])) {
            $existingId = (int) $row['id'];
        }
    }

    if ($existingId !== null && $schema['id'] !== null) {
        $sets = [];
        foreach (array_keys($data) as $column) {
            $sets[] = qi($column) . ' = :' . $column;
        }
        $sql = 'UPDATE ' . qi($schema['table'])
            . ' SET ' . implode(', ', $sets)
            . ' WHERE ' . qi($schema['id']) . ' = :row_id';
        $stmt = $pdo->prepare($sql);
        foreach ($data as $column => $value) {
            $stmt->bindValue(':' . $column, $value, PDO::PARAM_STR);
        }
        $stmt->bindValue(':row_id', $existingId, PDO::PARAM_INT);
        $stmt->execute();
    } else {
        if ($schema['created_at'] !== null) {
            $data[$schema['created_at']] = date('Y-m-d H:i:s');
        }

        $columns = array_keys($data);
        $columnSql = implode(', ', array_map('qi', $columns));
        $valuesSql = implode(', ', array_map(static fn (string $column): string => ':' . $column, $columns));
        $sql = 'INSERT INTO ' . qi($schema['table']) . ' (' . $columnSql . ') VALUES (' . $valuesSql . ')';
        $stmt = $pdo->prepare($sql);
        foreach ($data as $column => $value) {
            $stmt->bindValue(':' . $column, $value, PDO::PARAM_STR);
        }
        $stmt->execute();
    }

    return rib_get();
}
