<?php

declare(strict_types=1);

// DesignSystemRegistry loaded by the app-local JSONM runtime.

final class MyronSiteResetService
{
    public const CONFIRMATION_PHRASE = 'reset site';

    public function __construct(
        private readonly PDO $pdo,
        private readonly MyronContentRepository $content,
        private readonly MyronOnboardingStateRepository $onboarding,
        private readonly MyronBundleActivationRepository $bundles,
        private readonly MyronFileRepository $files,
        private readonly MyronSiteSettingsRepository $siteSettings,
        private readonly DesignSystemRegistry $designSystems,
    ) {
    }

    /**
     * @return array<string, mixed>
     */
    public function resetToBaseline(string $actorId): array
    {
        $actor = trim($actorId);
        if ($actor === '') {
            throw new InvalidArgumentException('An actor id is required to reset the site.');
        }

        $onboardingState = $this->onboarding->resetState();
        $bundleState = $this->bundles->clearStateWithAudit($actor, 'site-reset');
        $runtimeCounts = $this->clearRuntimeState();
        $fileResult = $this->files->purgeAllFiles();
        $settings = $this->siteSettings->resetToDefaults();
        $designResult = $this->designSystems->purgeStoredAndApplyBaseline();
        $contentCounts = $this->content->resetToBaselineSeed();

        return [
            'onboardingState' => $onboardingState,
            'activeBundles' => $bundleState,
            'runtimeCounts' => $runtimeCounts,
            'files' => $fileResult,
            'siteSettings' => $settings,
            'designSystems' => $designResult,
            'contentCounts' => $contentCounts,
            'baselinePages' => count($this->content->listPublishedPages()),
        ];
    }

    public function assertConfirmed(string $confirmationPhrase): void
    {
        if (trim($confirmationPhrase) !== self::CONFIRMATION_PHRASE) {
            throw new InvalidArgumentException('Type "' . self::CONFIRMATION_PHRASE . '" to reset the site to baseline.');
        }
    }

    /**
     * @return array<string, int>
     */
    private function clearRuntimeState(): array
    {
        $tables = [
            'funnel_quality_results',
            'funnel_audit_events',
            'funnel_branching_sessions',
            'funnel_visitor_deadlines',
            'funnel_flow_steps',
            'funnel_flows',
            'commerce_checkouts',
            'commerce_payment_providers',
        ];
        $counts = [];

        $this->pdo->beginTransaction();

        try {
            foreach ($tables as $table) {
                $counts[$table] = $this->tableCount($table);
                $this->pdo->exec('DELETE FROM ' . $table);
            }

            if ($this->pdo->inTransaction()) {
                $this->pdo->commit();
            }
        } catch (Throwable $exception) {
            if ($this->pdo->inTransaction()) {
                $this->pdo->rollBack();
            }

            throw $exception;
        }

        return $counts;
    }

    private function tableCount(string $table): int
    {
        return (int) $this->pdo->query('SELECT COUNT(*) FROM ' . $table)->fetchColumn();
    }
}
