<?php
/**
 * Design convention write handler with dry-run previews.
 *
 * @package LolaCoreForBricks
 */

declare(strict_types=1);

namespace LolaCoreForBricks\Handlers;

use LolaCoreForBricks\BricksEnv;
use LolaCoreForBricks\Gateways\ConventionGateway;
use LolaCoreForBricks\Support\BricksCodeGuard;
use LolaCoreForBricks\Support\CoveragePayload;
use LolaCoreForBricks\Support\DesignConventionStore;
use LolaCoreForBricks\Support\ExternalFrameworkDetector;

/**
 * Executes setDesignConvention.
 */
class ConventionHandler
{
    public function __construct(
        private readonly ?ConventionGateway $gateway = null
    ) {
    }

    /**
     * @param array<string, mixed> $params
     * @return array<string, mixed>
     */
    public function setDesignConvention(array $params, bool $dryRun = false): array
    {
        $guard = $this->environmentGuard($params);
        if ($guard !== null) {
            return $guard;
        }

        $detection = (new ExternalFrameworkDetector())->detect();
        $payload   = [
            'current_convention' => DesignConventionStore::get(),
            'detected_framework' => $detection,
            'compliance'         => DesignConventionStore::classComplianceStats(),
            'coverage'           => CoveragePayload::forResponse(),
        ];

        if ($dryRun) {
            return $this->preview('Design convention preview is ready.', $payload);
        }

        $result = ($this->gateway ?? new ConventionGateway())->setDesignConvention($params);
        if (($result['success'] ?? false) !== true) {
            return $result;
        }

        return array_merge($result, [
            'detected_framework' => $detection,
            'coverage'           => CoveragePayload::forResponse(),
        ]);
    }

    /**
     * @param array<string, mixed> $payload
     * @return array<string, mixed>
     */
    private function preview(string $message, array $payload): array
    {
        return array_merge(
            [
                'success' => true,
                'message' => $message,
                'dry_run' => true,
            ],
            $payload
        );
    }

    /**
     * @param array<string, mixed> $params
     * @return array<string, mixed>|null
     */
    private function environmentGuard(array $params = []): ?array
    {
        if ($rejection = BricksCodeGuard::rejectionResponse($params)) {
            return $rejection;
        }

        if (!BricksEnv::userCanReadDesignSystem()) {
            return $this->failure(
                'I need administrator access to save the Bricks design convention.',
                'forbidden'
            );
        }

        if (!BricksEnv::isAvailable() || !BricksEnv::meetsFloor()) {
            return $this->failure(
                'Bricks is not available on this site yet. Activate Bricks '
                . BricksEnv::FLOOR_VERSION . ' or newer, then try again.',
                'bricks_unavailable'
            );
        }

        return null;
    }

    /**
     * @return array{success: false, message: string, error: string}
     */
    private function failure(string $message, string $error): array
    {
        return [
            'success' => false,
            'message' => $message,
            'error'   => $error,
        ];
    }
}
