<?php

declare(strict_types=1);

use WHMCS\Database\Capsule;

final class HexaGameCloudModuleStorage
{
    public function recordOperation(string $operation, string $status, array $metadata = []): void
    {
        Capsule::table('mod_hexagamecloud_operations')->insert([
            'operation' => $operation,
            'status' => $status,
            'metadata' => json_encode($metadata, JSON_THROW_ON_ERROR),
            'created_at' => gmdate('Y-m-d H:i:s'),
        ]);
    }

    public function setLastError(string $message): void
    {
        Capsule::table('mod_hexagamecloud_installations')->updateOrInsert(
            ['id' => 1],
            [
                'last_error' => $message,
                'updated_at' => gmdate('Y-m-d H:i:s'),
            ]
        );
    }

    public function getLastError(): ?string
    {
        $row = Capsule::table('mod_hexagamecloud_installations')->where('id', 1)->first();
        return $row?->last_error;
    }

    public function updateSyncCursor(?string $cursor): void
    {
        Capsule::table('mod_hexagamecloud_sync_cursors')->updateOrInsert(
            ['id' => 1],
            [
                'events_cursor' => $cursor,
                'last_poll_at' => gmdate('Y-m-d H:i:s'),
                'updated_at' => gmdate('Y-m-d H:i:s'),
            ]
        );
    }

    public function getSyncCursor(): ?string
    {
        $row = Capsule::table('mod_hexagamecloud_sync_cursors')->where('id', 1)->first();
        return $row?->events_cursor;
    }

    public function storeRemoteEvent(string $remoteId, string $eventType, array $payload, string $status = 'pending'): void
    {
        $existing = Capsule::table('mod_hexagamecloud_events')
            ->where('remote_event_id', $remoteId)
            ->first();

        if ($existing) {
            return;
        }

        Capsule::table('mod_hexagamecloud_events')->insert([
            'remote_event_id' => $remoteId,
            'event_type' => $eventType,
            'payload' => json_encode($payload, JSON_THROW_ON_ERROR),
            'status' => $status,
            'created_at' => gmdate('Y-m-d H:i:s'),
        ]);
    }

    public function listLocalEvents(int $limit = 50): array
    {
        return Capsule::table('mod_hexagamecloud_events')
            ->orderBy('id', 'desc')
            ->limit($limit)
            ->get()
            ->map(static fn ($row) => (array) $row)
            ->all();
    }

    public function countLocalEventsByStatus(string $status): int
    {
        return (int) Capsule::table('mod_hexagamecloud_events')->where('status', $status)->count();
    }

    public function getLocalEvent(int $id): ?array
    {
        $row = Capsule::table('mod_hexagamecloud_events')->where('id', $id)->first();
        return $row ? (array) $row : null;
    }

    public function updateLocalEventStatus(int $id, string $status): void
    {
        Capsule::table('mod_hexagamecloud_events')->where('id', $id)->update([
            'status' => $status,
            'processed_at' => gmdate('Y-m-d H:i:s'),
        ]);
    }

    public function saveReconciliationRun(array $result, string $mode): void
    {
        $issues = $result['issues'] ?? [];
        Capsule::table('mod_hexagamecloud_reconciliation')->insert([
            'run_id' => (string) ($result['runId'] ?? ''),
            'mode' => $mode,
            'issue_count' => is_array($issues) ? count($issues) : 0,
            'payload' => json_encode($result, JSON_THROW_ON_ERROR),
            'created_at' => gmdate('Y-m-d H:i:s'),
        ]);
    }

    public function listReconciliationRuns(int $limit = 20): array
    {
        return Capsule::table('mod_hexagamecloud_reconciliation')
            ->orderBy('id', 'desc')
            ->limit($limit)
            ->get()
            ->map(static fn ($row) => (array) $row)
            ->all();
    }
}
