<?php

namespace App\Services;

use App\Models\Visit;
use App\Models\VisitStatusHistory;
use App\Exceptions\InvalidStatusTransitionException;

class VisitStatusService
{
    private const ALLOWED_TRANSITIONS = [
        'Pending Visitor' => ['Pending Approve', 'Canceled', 'Expired'],
        'Pending Host' => ['Pending Approve', 'Canceled'],
        'Pending Approve' => ['Approved', 'Rejected', 'Pending Host', 'Canceled'],
        'Approved' => ['Completed', 'Canceled'],
        'Rejected' => [],
        'Canceled' => [],
        'Completed' => [],
        'Expired' => [],
    ];

    /**
     * Check if transition is allowed
     */
    public function canTransition(string $from, string $to): bool
    {
        return in_array($to, self::ALLOWED_TRANSITIONS[$from] ?? []);
    }

    /**
     * Transition visit to new status
     */
    public function transition(
        Visit $visit,
        string $newStatus,
        ?string $reason = null,
        ?string $changedByEmail = null,
        ?string $changedByName = null
    ): Visit {
        if (!$this->canTransition($visit->status, $newStatus)) {
            throw new InvalidStatusTransitionException(
                "Cannot transition from {$visit->status} to {$newStatus}"
            );
        }

        $oldStatus = $visit->status;
        $visit->status = $newStatus;

        if ($reason) {
            $visit->rejection_reason = $reason;
        }

        if ($changedByEmail) {
            $visit->reviewed_by_email = $changedByEmail;
            $visit->reviewed_at = now();
        }

        $visit->save();

        // Log status history
        VisitStatusHistory::create([
            'visit_id' => $visit->id,
            'from_status' => $oldStatus,
            'to_status' => $newStatus,
            'changed_by_email' => $changedByEmail,
            'changed_by_name' => $changedByName,
            'reason' => $reason,
        ]);

        return $visit;
    }

    /**
     * Get allowed transitions for a status
     */
    public function getAllowedTransitions(string $status): array
    {
        return self::ALLOWED_TRANSITIONS[$status] ?? [];
    }
}
