<?php

namespace App\Domain\Facility\Services;

use App\Domain\Facility\Enums\FacilityStatus;
use App\Domain\Facility\Events\FacilityStatusChanged;
use App\Domain\Facility\Models\Facility;
use App\Domain\Shared\Exceptions\DomainException;
use App\Models\User;
use Illuminate\Support\Facades\DB;

class FacilityService
{
    private const VALID_TRANSITIONS = [
        'active' => ['maintenance', 'closed', 'reserved', 'unavailable'],
        'maintenance' => ['active', 'closed'],
        'closed' => ['active', 'maintenance'],
        'reserved' => ['active'],
        'unavailable' => ['active'],
    ];

    public function create(array $data, User $creator): Facility
    {
        return DB::transaction(function () use ($data, $creator) {
            return Facility::create([
                ...$data,
                'created_by' => $creator->id,
            ]);
        });
    }

    public function update(Facility $facility, array $data): Facility
    {
        return DB::transaction(function () use ($facility, $data) {
            $facility->update($data);
            return $facility->fresh();
        });
    }

    public function changeStatus(Facility $facility, string $newStatus, ?User $actor = null): Facility
    {
        return DB::transaction(function () use ($facility, $newStatus, $actor) {
            $currentStatus = $facility->status->value ?? $facility->status;
            $allowed = self::VALID_TRANSITIONS[$currentStatus] ?? [];

            if (!in_array($newStatus, $allowed)) {
                throw new DomainException(
                    "لا يمكن تغيير الحالة من '{$facility->status->label()}' إلى '" . FacilityStatus::from($newStatus)->label() . "'"
                );
            }

            $facility->update(['status' => $newStatus]);

            $fresh = $facility->fresh();
            if ($actor) {
                FacilityStatusChanged::dispatch($fresh, $currentStatus, $newStatus, $actor);
            }

            return $fresh;
        });
    }

    public function delete(Facility $facility): void
    {
        DB::transaction(function () use ($facility) {
            $facility->delete();
        });
    }
}
