<?php
/**
 * BookiFlex Onboarding Extension
 *
 * @package    BookiFlex
 * @subpackage Onboarding
 * @author     BookiFlex
 * @copyright  Copyright (c) 2025 BookiFlex
 * @license    GPL-2.0-or-later
 *
 * @link       https://bookiflex.com
 */

declare(strict_types=1);

namespace BookiFlex\Extensions\Onboarding\Service;

use BookiFlex\Core\Infrastructure\Storage\OptionRepositoryInterface;
use BookiFlex\Extensions\Onboarding\ValueObject\OnboardingMode;
use BookiFlex\Extensions\Onboarding\Exception\OnboardingAlreadyCompletedException;

defined( 'ABSPATH' ) || exit;

/**
 * Onboarding State Manager
 *
 * Manages onboarding completion state via WordPress options.
 * Uses lightweight OptionRepositoryInterface instead of full ORM entity.
 *
 * @package BookiFlex\Extensions\Onboarding\Service
 * @since   1.0.0
 */
class OnboardingStateManager
{
    public const OPTION_COMPLETED = 'onboarding_completed';
    public const OPTION_NEEDS_REDIRECT = 'onboarding_needs_redirect';
    private const OPTION_METADATA = 'onboarding_metadata';

    /**
     * OnboardingStateManager constructor
     *
     * @param OptionRepositoryInterface $optionRepository Option repository
     */
    public function __construct(
        private readonly OptionRepositoryInterface $optionRepository
    ) {
    }

    /**
     * Check if onboarding is completed
     *
     * @return bool True if onboarding is completed
     */
    public function isCompleted(): bool
    {
        return (bool) $this->optionRepository->get(self::OPTION_COMPLETED, false);
    }

    /**
     * Mark onboarding as complete with metadata
     *
     * @param  OnboardingMode       $mode     Onboarding mode that was completed
     * @param  array<string, mixed> $metadata Additional metadata (entity IDs, etc.)
     * @return void
     * @throws OnboardingAlreadyCompletedException If onboarding already completed
     */
    public function markComplete(OnboardingMode $mode, array $metadata): void
    {
        if ($this->isCompleted()) {
            throw new OnboardingAlreadyCompletedException(
                'Onboarding has already been completed'
            );
        }

        $this->optionRepository->set(self::OPTION_COMPLETED, true);
        $this->optionRepository->set(
            self::OPTION_METADATA, [
            'mode' => $mode->value,
            'completedAt' => (new \DateTime())->format('c'),
            'metadata' => $metadata,
            ]
        );
        $this->clearRedirectFlag();
    }

    /**
     * Retrieve onboarding metadata (audit trail)
     *
     * @return array<string, mixed>|null Metadata array or null if not completed
     */
    public function getMetadata(): ?array
    {
        return $this->optionRepository->get(self::OPTION_METADATA);
    }

    /**
     * Reset onboarding state (for testing purposes)
     *
     * @return void
     */
    public function reset(): void
    {
        $this->optionRepository->delete(self::OPTION_COMPLETED);
        $this->optionRepository->delete(self::OPTION_METADATA);
        $this->optionRepository->delete(self::OPTION_NEEDS_REDIRECT);
    }

    /**
     * Mark that user needs redirect to onboarding page
     *
     * Should be called after plugin activation if onboarding not completed.
     *
     * @return void
     */
    public function markNeedsRedirect(): void
    {
        $this->optionRepository->set(self::OPTION_NEEDS_REDIRECT, true);
    }

    /**
     * Check if redirect to onboarding page is needed
     *
     * @return bool True if redirect is needed
     */
    public function needsRedirect(): bool
    {
        return (bool) $this->optionRepository->get(self::OPTION_NEEDS_REDIRECT, false);
    }

    /**
     * Clear redirect flag
     *
     * Should be called after redirecting user to onboarding page.
     *
     * @return void
     */
    public function clearRedirectFlag(): void
    {
        $this->optionRepository->delete(self::OPTION_NEEDS_REDIRECT);
    }
}
