<?php

declare(strict_types=1);

namespace HyperfTest\Cases\Unit\Model;

use App\Model\AggregateRefreshQueue;
use Carbon\Carbon;
use PHPUnit\Framework\TestCase;

/**
 * @internal
 * @coversNothing
 */
class AggregateRefreshQueueTest extends TestCase
{
    protected function runInCoroutine(callable $callback): void
    {
        if (\Swoole\Coroutine::getCid() > 0) {
            $callback();
            return;
        }

        $exception = null;
        \Swoole\Coroutine\run(static function () use ($callback, &$exception): void {
            try {
                $callback();
            } catch (\Throwable $e) {
                $exception = $e;
            }
        });
        if ($exception) {
            throw $exception;
        }
    }

    private function uniqueRefreshDate(): string
    {
        // 与 ApiKeyTest 的 bin2hex(random_bytes(4)) 同源策略：用唯一性而非全表清理来隔离用例
        return sprintf('20%02d-%02d-%02d', random_int(50, 99), random_int(1, 12), random_int(1, 28));
    }

    public function test_attributes_persist_correctly(): void
    {
        $this->runInCoroutine(function (): void {
            $unique_date = $this->uniqueRefreshDate();

            try {
                AggregateRefreshQueue::query()->create([
                    'refresh_date' => $unique_date,
                    'aggregate_view' => 'orders_daily_by_created',
                    'created_at' => Carbon::now(),
                ]);

                $row = AggregateRefreshQueue::query()->where('refresh_date', $unique_date)->first();

                $this->assertNotNull($row);
                $this->assertSame($unique_date, $row->refresh_date);
                $this->assertSame('orders_daily_by_created', $row->aggregate_view);
                $this->assertInstanceOf(Carbon::class, $row->created_at);
            } finally {
                AggregateRefreshQueue::query()->where('refresh_date', $unique_date)->delete();
            }
        });
    }

    public function test_insert_or_ignore_dedups_on_composite_pk(): void
    {
        $this->runInCoroutine(function (): void {
            $unique_date = $this->uniqueRefreshDate();

            $payload = [
                'refresh_date' => $unique_date,
                'aggregate_view' => 'orders_daily_by_created',
                'created_at' => Carbon::now(),
            ];

            try {
                AggregateRefreshQueue::query()->insertOrIgnore($payload);
                AggregateRefreshQueue::query()->insertOrIgnore($payload);

                $count = AggregateRefreshQueue::query()->where('refresh_date', $unique_date)->count();
                $this->assertSame(1, $count);
            } finally {
                AggregateRefreshQueue::query()->where('refresh_date', $unique_date)->delete();
            }
        });
    }
}
