<?php

namespace App\Services\Draw;

use App\Models\Draw;
use App\Lottery\DrawStatus;
use Illuminate\Support\Facades\DB;

final class DrawAdminActionService
{
    public function __construct(
        private readonly DrawCancelBetRefundService $cancelBetRefund,
    ) {}

    public function manualClose(Draw $draw): Draw
    {
        return DB::transaction(function () use ($draw): Draw {
            /** @var Draw $locked */
            $locked = Draw::query()->whereKey($draw->id)->lockForUpdate()->firstOrFail();
            if (! in_array($locked->status, [DrawStatus::Open->value, DrawStatus::Pending->value], true)) {
                throw new \RuntimeException('draw_not_closeable');
            }

            $locked->forceFill([
                'status' => DrawStatus::Closing->value,
                'close_time' => now(),
            ])->save();

            return $locked->refresh();
        });
    }

    public function cancelBeforeResult(Draw $draw): Draw
    {
        return DB::transaction(function () use ($draw): Draw {
            /** @var Draw $locked */
            $locked = Draw::query()->whereKey($draw->id)->lockForUpdate()->firstOrFail();
            if (! in_array($locked->status, [
                DrawStatus::Pending->value,
                DrawStatus::Open->value,
                DrawStatus::Closing->value,
                DrawStatus::Closed->value,
            ], true)) {
                throw new \RuntimeException('draw_not_cancelable');
            }
            if ($locked->resultBatches()->exists()) {
                throw new \RuntimeException('draw_result_exists');
            }

            $this->cancelBetRefund->refundOpenBetsForDraw($locked);

            $locked->forceFill(['status' => DrawStatus::Cancelled->value])->save();

            return $locked->refresh();
        });
    }
}
