import fastifyStatic from '@fastify/static';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
import { healthRoutes } from '../modules/cli-configuration/interface-adapters/controllers/http/health.routes.js';
import { settingsRoutes } from '../modules/cli-configuration/interface-adapters/controllers/http/settings.routes.js';
import { reviewRoutes } from '../modules/review-execution/interface-adapters/controllers/http/reviews.routes.js';
import { statsRoutes } from '../modules/statistics-insights/interface-adapters/controllers/http/stats.routes.js';
import { overviewRoutes } from '../modules/statistics-insights/interface-adapters/controllers/http/overview.routes.js';
import { mrTrackingRoutes } from '../modules/tracking/interface-adapters/controllers/http/mrTracking.routes.js';
import { loadProjectConfig } from '../config/projectConfig.js';
import { mrTrackingAdvancedRoutes } from '../modules/tracking/interface-adapters/controllers/http/mrTrackingAdvanced.routes.js';
import { logsRoutes } from '../modules/cli-configuration/interface-adapters/controllers/http/logs.routes.js';
import { cliStatusRoutes } from '../modules/cli-configuration/interface-adapters/controllers/http/cliStatus.routes.js';
import { projectConfigRoutes } from '../modules/cli-configuration/interface-adapters/controllers/http/projectConfig.routes.js';
import { ProjectConfigFileSystemGateway } from '../modules/cli-configuration/interface-adapters/gateways/projectConfig.fileSystem.gateway.js';
import { UpdateProjectConfigUseCase } from '../modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.js';
import { repositoriesRoutes } from '../modules/cli-configuration/interface-adapters/controllers/http/repositories.routes.js';
import { AddRepositoriesToConfigUseCase } from '../modules/cli-configuration/usecases/cli/addRepositoriesToConfig.usecase.js';
import { RemoveRepositoryFromConfigUseCase } from '../modules/cli-configuration/usecases/cli/removeRepositoryFromConfig.usecase.js';
import { ToggleRepositoryEnabledUseCase } from '../modules/cli-configuration/usecases/cli/toggleRepositoryEnabled.usecase.js';
import { AddRepositoryFromDashboardUseCase } from '../modules/cli-configuration/usecases/dashboardRepositories/addRepositoryFromDashboard.usecase.js';
import { RemoveRepositoryFromDashboardUseCase } from '../modules/cli-configuration/usecases/dashboardRepositories/removeRepositoryFromDashboard.usecase.js';
import { UpdateRepositoryEnabledFromDashboardUseCase } from '../modules/cli-configuration/usecases/dashboardRepositories/updateRepositoryEnabledFromDashboard.usecase.js';
import { enrichSingleRepository, resolveActiveConfigPath } from '../frameworks/config/configLoader.js';
import { existsSync, readFileSync, statSync, writeFileSync } from 'node:fs';
import { cleanupRoutes } from '../modules/data-lifecycle/interface-adapters/controllers/http/cleanup.routes.js';
import { versionRoutes } from '../modules/cli-configuration/interface-adapters/controllers/http/version.routes.js';
import { insightsRoutes } from '../modules/statistics-insights/interface-adapters/controllers/http/insights.routes.js';
import { registerWebSocketRoutes } from '../main/websocket.js';
import { setupWizardRoutes } from '../modules/setup-wizard/interface-adapters/controllers/http/setupWizard.routes.js';
import { SetupRunRegistry } from '../modules/setup-wizard/usecases/streamSetupRun.usecase.js';
import { SetupProcessChildProcessGateway } from '../modules/setup-wizard/interface-adapters/gateways/setupProcess.childProcess.gateway.js';
import { SetupStateFileSystemGateway } from '../modules/setup-wizard/interface-adapters/gateways/setupState.fileSystem.gateway.js';
import { emberChatRoutes } from '../modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.js';
import { EmberAnswerTransportClaudeGateway } from '../modules/ember-chat/interface-adapters/gateways/emberAnswerTransport.claude.gateway.js';
import { EmberReadDataCompositeGateway } from '../modules/ember-chat/interface-adapters/gateways/emberReadData.composite.gateway.js';
import { ClaudeSessionCliGateway } from '../modules/claude-invocation/interface-adapters/gateways/claudeSession.cli.gateway.js';
import { defaultProcessRunner } from '../frameworks/claude/claudeInvoker.js';
import { ProcessEnvironmentGateway } from '../modules/claude-invocation/interface-adapters/gateways/environment.process.gateway.js';
import { getConfigDir } from '../shared/services/configDir.js';
import { homedir } from 'node:os';
import { handleGitLabWebhook } from '../modules/platform-integration/interface-adapters/controllers/webhook/gitlab.controller.js';
import { handleGitHubWebhook } from '../modules/platform-integration/interface-adapters/controllers/webhook/github.controller.js';
import { cancelJob, getJobStatus, enqueueReview, getJobsStatus, setProjectConcurrencyCap, setGlobalConcurrency, getRunningCount, getTotalCapacity, } from '../frameworks/queue/pQueueAdapter.js';
import { RecomputeGlobalConcurrencyUseCase } from '../modules/cli-configuration/usecases/projectConfig/recomputeGlobalConcurrency.usecase.js';
import { RepositoriesListRuntimeConfigGateway } from '../modules/cli-configuration/interface-adapters/gateways/repositoriesList.runtimeConfig.gateway.js';
import { GitLabThreadFetchGateway, defaultGitLabExecutor } from '../modules/platform-integration/interface-adapters/gateways/threadFetch.gitlab.gateway.js';
import { GitLabDiffMetadataFetchGateway } from '../modules/platform-integration/interface-adapters/gateways/diffMetadataFetch.gitlab.gateway.js';
import { GitHubThreadFetchGateway, defaultGitHubExecutor } from '../modules/platform-integration/interface-adapters/gateways/threadFetch.github.gateway.js';
import { GitHubDiffMetadataFetchGateway } from '../modules/platform-integration/interface-adapters/gateways/diffMetadataFetch.github.gateway.js';
import { GitLabDiffStatsFetchGateway } from '../modules/statistics-insights/interface-adapters/gateways/diffStatsFetch.gitlab.gateway.js';
import { GitHubDiffStatsFetchGateway } from '../modules/statistics-insights/interface-adapters/gateways/diffStatsFetch.github.gateway.js';
import { TrackAssignmentUseCase } from '../modules/tracking/usecases/tracking/trackAssignment.usecase.js';
import { RecordReviewCompletionUseCase } from '../modules/tracking/usecases/tracking/recordReviewCompletion.usecase.js';
import { RecordPushUseCase } from '../modules/tracking/usecases/tracking/recordPush.usecase.js';
import { TransitionStateUseCase } from '../modules/tracking/usecases/tracking/transitionState.usecase.js';
import { CheckFollowupNeededUseCase } from '../modules/tracking/usecases/tracking/checkFollowupNeeded.usecase.js';
import { SyncThreadsUseCase } from '../modules/tracking/usecases/tracking/syncThreads.usecase.js';
import { RecordBypassUseCase } from '../modules/tracking/usecases/tracking/recordBypass.usecase.js';
import { HandlePlatformApprovalUseCase } from '../modules/tracking/usecases/tracking/handlePlatformApproval.usecase.js';
import { GitLabNoteCommentPostCliGateway } from '../modules/platform-integration/interface-adapters/gateways/cli/noteCommentPost.gitlab.cli.gateway.js';
import { GitHubNoteCommentPostCliGateway } from '../modules/platform-integration/interface-adapters/gateways/cli/noteCommentPost.github.cli.gateway.js';
import { GitLabApprovalRevocationCliGateway } from '../modules/platform-integration/interface-adapters/gateways/cli/approvalRevocation.gitlab.cli.gateway.js';
import { GitHubApprovalRevocationCliGateway } from '../modules/platform-integration/interface-adapters/gateways/cli/approvalRevocation.github.cli.gateway.js';
import { ReviewContextFileSystemGateway } from '../modules/review-execution/interface-adapters/gateways/reviewContext.fileSystem.gateway.js';
import { tokenUsageRoutes } from '../modules/token-accounting/interface-adapters/controllers/http/tokenUsage.routes.js';
import { worktreeOverviewRoutes } from '../modules/worktree-management/interface-adapters/controllers/http/worktreeOverview.routes.js';
import { SummarizeTokenUsageUseCase } from '../modules/token-accounting/usecases/summarizeTokenUsage/summarizeTokenUsage.usecase.js';
import { TokenUsageSummaryPresenter } from '../modules/token-accounting/interface-adapters/presenters/tokenUsageSummary.presenter.js';
import { FilesystemTokenUsageGateway } from '../modules/token-accounting/interface-adapters/gateways/tokenUsage/tokenUsage.filesystem.gateway.js';
import { budgetRoutes } from '../modules/token-accounting/interface-adapters/controllers/http/budget.routes.js';
import { FilesystemBudgetGateway } from '../modules/token-accounting/interface-adapters/gateways/budget/budget.filesystem.gateway.js';
import { GetBudgetStatusUseCase } from '../modules/token-accounting/usecases/getBudgetStatus/getBudgetStatus.usecase.js';
import { UpdateBudgetUseCase } from '../modules/token-accounting/usecases/updateBudget/updateBudget.usecase.js';
import { EnforceBudgetUseCase } from '../modules/token-accounting/usecases/enforceBudget/enforceBudget.usecase.js';
import { BudgetStatusPresenter } from '../modules/token-accounting/interface-adapters/presenters/budgetStatus.presenter.js';
import { BUDGET_DEFAULT_USD } from '../modules/token-accounting/entities/budget/budgetConfig.schema.js';
import { broadcastBudgetExceeded, broadcastBudgetStatus, broadcastPendingChanged } from '../main/websocket.js';
import { PendingReviewRequestFileSystemGateway } from '../modules/review-execution/interface-adapters/gateways/pendingReviewRequest.fileSystem.gateway.js';
import { ListPendingReviewsUseCase } from '../modules/review-execution/usecases/listPendingReviews.usecase.js';
import { ConfirmPendingReviewUseCase } from '../modules/review-execution/usecases/confirmPendingReview.usecase.js';
import { DismissPendingReviewUseCase } from '../modules/review-execution/usecases/dismissPendingReview.usecase.js';
import { GateClaudeInvocationUseCase } from '../modules/review-execution/usecases/gateClaudeInvocation.usecase.js';
import { PendingReviewPresenter } from '../modules/review-execution/interface-adapters/presenters/pendingReview.presenter.js';
import { pendingReviewsRoutes } from '../modules/review-execution/interface-adapters/controllers/http/pendingReviews.routes.js';
import { createDefaultClaudeInvokerDependencies, } from '../frameworks/claude/claudeInvoker.js';
import { checkVersion } from '../modules/cli-configuration/usecases/version/checkVersion.usecase.js';
import { triggerSelfUpdate } from '../modules/cli-configuration/usecases/version/triggerSelfUpdate.usecase.js';
import { NpmPackageVersionGateway } from '../modules/cli-configuration/interface-adapters/gateways/packageVersion.npm.gateway.js';
import { VersionCacheMemoryGateway } from '../modules/cli-configuration/interface-adapters/gateways/versionCache.memory.gateway.js';
import { SelfUpdateCliGateway } from '../modules/cli-configuration/interface-adapters/gateways/selfUpdate.cli.gateway.js';
import { InstallTypeDetectorFsGateway } from '../modules/cli-configuration/interface-adapters/gateways/installTypeDetector.fs.gateway.js';
import { broadcastBackfillProgress } from '../main/websocket.js';
import { createClaudeInsightsInvoker } from '../frameworks/claude/claudeInsightsInvoker.js';
import { getDefaultLanguage, getWorktreeStaleThresholdHours } from '../frameworks/settings/runtimeSettings.js';
import { detectDegradedWorktrees } from '../modules/worktree-management/usecases/detectDegradedWorktrees.usecase.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
function readVersion() {
    const packageJsonPath = join(__dirname, '..', '..', 'package.json');
    const raw = readFileSync(packageJsonPath, 'utf-8');
    return JSON.parse(raw).version;
}
const currentVersion = readVersion();
const packageVersionGateway = new NpmPackageVersionGateway();
const versionCache = new VersionCacheMemoryGateway();
const selfUpdateCommand = new SelfUpdateCliGateway();
const installTypeDetector = new InstallTypeDetectorFsGateway();
export async function registerRoutes(app, deps) {
    await app.register(fastifyStatic, {
        root: join(__dirname, '..', 'dashboard'),
        prefix: '/dashboard/',
    });
    await app.register(healthRoutes, {
        getConfig: () => ({ version: currentVersion }),
        versionCache,
        supervisorStatusStore: deps.supervisorStatusStore,
    });
    await app.register(settingsRoutes);
    await app.register(reviewRoutes, {
        reviewFileGateway: deps.reviewFileGateway,
        reviewRequestTrackingGateway: deps.reviewRequestTrackingGateway,
        getRepositories: () => deps.config.repositories,
        queuePort: { getJobStatus, cancelJob },
        logger: deps.logger,
    });
    await app.register(statsRoutes, {
        statsGateway: deps.statsGateway,
        getRepositories: () => deps.config.repositories,
        diffStatsFetchGateways: {
            gitlab: new GitLabDiffStatsFetchGateway(defaultGitLabExecutor),
            github: new GitHubDiffStatsFetchGateway(defaultGitHubExecutor),
        },
        broadcastBackfillProgress,
        logger: deps.logger,
    });
    const projectConfigGateway = new ProjectConfigFileSystemGateway();
    const updateProjectConfig = new UpdateProjectConfigUseCase(projectConfigGateway);
    const recomputeGlobalConcurrency = new RecomputeGlobalConcurrencyUseCase({
        repositoriesListGateway: new RepositoriesListRuntimeConfigGateway(() => deps.config.repositories),
        projectConfigGateway,
        queueCapacityPort: {
            setGlobalConcurrency,
            setProjectConcurrencyCap,
        },
    });
    recomputeGlobalConcurrency.execute({});
    await app.register(overviewRoutes, {
        getRepositories: () => deps.config.repositories,
        getActiveJobs: () => getJobsStatus().active.map((job) => ({
            id: job.id,
            mrNumber: job.mrNumber,
            project: job.project,
            mrUrl: job.mrUrl,
            status: job.status,
            startedAt: job.startedAt ?? null,
            title: job.title,
            jobType: job.jobType,
        })),
        statsGateway: deps.statsGateway,
        reviewFileGateway: deps.reviewFileGateway,
        projectConfigGateway,
        getCapacity: () => ({ running: getRunningCount(), max: getTotalCapacity() }),
    });
    await app.register(mrTrackingRoutes, {
        reviewRequestTrackingGateway: deps.reviewRequestTrackingGateway,
        getQualityThreshold: (projectPath) => loadProjectConfig(projectPath)?.qualityThreshold ?? null,
    });
    const tokenUsageGateway = new FilesystemTokenUsageGateway();
    await app.register(tokenUsageRoutes, {
        summarizeTokenUsage: new SummarizeTokenUsageUseCase(tokenUsageGateway),
        presenter: new TokenUsageSummaryPresenter(),
    });
    await app.register(worktreeOverviewRoutes, {
        worktreeGateway: deps.worktreeGateway,
        presenter: deps.worktreePanelPresenter,
        schedulerControls: deps.sweepSchedulerControls,
        logger: deps.logger,
        detectDegradedWorktrees: (entries) => detectDegradedWorktrees({
            entries,
            staleThresholdMs: getWorktreeStaleThresholdHours() * 60 * 60 * 1000,
            now: () => new Date(),
        }, { healthProbe: deps.worktreeHealthProbeGateway }),
        forceCleanupLock: deps.forceCleanupLock,
        removeWorktreeForCleanup: (identity) => {
            const firstEnabled = deps.config.repositories.find((repository) => repository.enabled);
            const sourceCheckoutPath = firstEnabled?.localPath ?? '';
            return deps.worktreeGateway.remove({ identity, sourceCheckoutPath, force: true });
        },
    });
    const budgetGateway = new FilesystemBudgetGateway();
    const existingBudget = await budgetGateway.load();
    if (existingBudget === null) {
        await budgetGateway.save({ limitUsd: BUDGET_DEFAULT_USD });
    }
    const getBudgetStatus = new GetBudgetStatusUseCase({ budgetGateway, tokenUsageGateway });
    const updateBudget = new UpdateBudgetUseCase({ budgetGateway });
    const enforceBudget = new EnforceBudgetUseCase({ getBudgetStatus });
    const budgetStatusPresenter = new BudgetStatusPresenter();
    await app.register(budgetRoutes, {
        getBudgetStatus,
        updateBudget,
        budgetGateway,
        presenter: budgetStatusPresenter,
        getRepositories: () => deps.config.repositories,
    });
    const pendingReviewRequestGateway = new PendingReviewRequestFileSystemGateway();
    const listPendingReviews = new ListPendingReviewsUseCase({ pendingReviewRequestGateway });
    const confirmPendingReview = new ConfirmPendingReviewUseCase({
        pendingReviewRequestGateway,
        queuePort: {
            hasActiveJob: (jobId) => {
                const status = getJobStatus(jobId);
                return status === 'queued' || status === 'running';
            },
            getJobStatus,
        },
        enqueue: enqueueReview,
        // The persisted ReviewJob snapshot lets us re-enqueue with the SAME inline
        // processor used at webhook time (rehydrated on confirm). No registry is
        // needed in V0 because all pending requests are confirmed by the SAME
        // running process; surviving restart simply means the user must re-trigger
        // the webhook after a restart if they want the original processor closure.
        resolveProcessor: () => async () => {
            deps.logger.warn('Pending review confirmed across processor rehydration — Claude invocation skipped (V0 limitation).');
        },
        logger: deps.logger,
    });
    const dismissPendingReview = new DismissPendingReviewUseCase({
        pendingReviewRequestGateway,
        queuePort: {
            hasActiveJob: (jobId) => {
                const status = getJobStatus(jobId);
                return status === 'queued' || status === 'running';
            },
        },
        logger: deps.logger,
    });
    const gateClaudeInvocation = new GateClaudeInvocationUseCase({
        triggerMode: deps.config.triggerMode,
        pendingReviewRequestGateway,
        enqueue: enqueueReview,
        broadcastPendingChanged: () => broadcastPendingChanged(),
        logger: deps.logger,
    });
    await app.register(pendingReviewsRoutes, {
        listPendingReviews,
        confirmPendingReview,
        dismissPendingReview,
        presenter: new PendingReviewPresenter(),
    });
    const claudeInvokerDeps = {
        ...createDefaultClaudeInvokerDependencies(),
        getBudgetStatus,
        budgetStatusPresenter,
        broadcastBudgetStatus,
        getEnabledLocalPaths: () => deps.config.repositories.filter((repository) => repository.enabled).map((repository) => repository.localPath),
        // Reuse the shared invocation deps so timers (server.ts) and review jobs
        // see the same BillingState / SupervisorHealth / completion bridge.
        invocation: deps.claudeInvocationDeps,
    };
    const threadFetchGatewayFactory = (platform) => platform === 'github'
        ? new GitHubThreadFetchGateway(defaultGitHubExecutor)
        : new GitLabThreadFetchGateway(defaultGitLabExecutor);
    await app.register(mrTrackingAdvancedRoutes, {
        getRepositories: () => deps.config.repositories,
        reviewRequestTrackingGateway: deps.reviewRequestTrackingGateway,
        reviewContextGateway: new ReviewContextFileSystemGateway(),
        threadFetchGatewayFactory,
        diffMetadataFetchGatewayFactory: (platform) => platform === 'github'
            ? new GitHubDiffMetadataFetchGateway(defaultGitHubExecutor)
            : new GitLabDiffMetadataFetchGateway(defaultGitLabExecutor),
        diffStatsFetchGatewayFactory: (platform) => platform === 'github'
            ? new GitHubDiffStatsFetchGateway(defaultGitHubExecutor)
            : new GitLabDiffStatsFetchGateway(defaultGitLabExecutor),
        createSyncThreadsUseCase: (platform) => new SyncThreadsUseCase(deps.reviewRequestTrackingGateway, threadFetchGatewayFactory(platform)),
        recordReviewCompletion: new RecordReviewCompletionUseCase(deps.reviewRequestTrackingGateway),
        enforceBudget,
        broadcastBudgetExceeded,
        claudeInvokerDeps,
        gateClaudeInvocation,
        logger: deps.logger,
    });
    await app.register(cleanupRoutes, {
        reviewFileGateway: deps.reviewFileGateway,
        reviewLogFileGateway: deps.reviewLogFileGateway,
        getRepositories: () => deps.config.repositories,
        logger: deps.logger,
    });
    await app.register(versionRoutes, {
        checkVersion,
        triggerSelfUpdate,
        currentVersion,
        packageVersionGateway,
        versionCache,
        selfUpdateCommand,
        installTypeDetector,
        serverPort: deps.config.server.port,
    });
    await app.register(insightsRoutes, {
        statsGateway: deps.statsGateway,
        insightsGateway: deps.insightsGateway,
        reviewFileGateway: deps.reviewFileGateway,
        reviewRequestTrackingGateway: deps.reviewRequestTrackingGateway,
        logger: deps.logger,
        claudeInvoker: createClaudeInsightsInvoker(),
        language: getDefaultLanguage(),
    });
    await app.register(logsRoutes);
    await app.register(cliStatusRoutes);
    await app.register(projectConfigRoutes, {
        updateProjectConfig,
        onSaved: () => {
            recomputeGlobalConcurrency.execute({});
        },
    });
    await registerWebSocketRoutes(app, deps);
    const trackingGw = deps.reviewRequestTrackingGateway;
    const threadFetchGw = new GitLabThreadFetchGateway(defaultGitLabExecutor);
    const removeWorktreeAction = (input) => deps.worktreeGateway.remove({
        identity: input.identity,
        sourceCheckoutPath: input.sourceCheckoutPath,
    });
    app.post('/webhooks/gitlab', async (request, reply) => {
        await handleGitLabWebhook(request, reply, deps.logger, trackingGw, {
            reviewContextGateway: deps.reviewContextGateway,
            threadFetchGateway: threadFetchGw,
            diffMetadataFetchGateway: new GitLabDiffMetadataFetchGateway(defaultGitLabExecutor),
            diffStatsFetchGateway: new GitLabDiffStatsFetchGateway(defaultGitLabExecutor),
            trackAssignment: new TrackAssignmentUseCase(trackingGw),
            recordCompletion: new RecordReviewCompletionUseCase(trackingGw),
            recordPush: new RecordPushUseCase(trackingGw),
            transitionState: new TransitionStateUseCase(trackingGw),
            checkFollowupNeeded: new CheckFollowupNeededUseCase(trackingGw),
            syncThreads: new SyncThreadsUseCase(trackingGw, threadFetchGw),
            enforceBudget,
            broadcastBudgetExceeded,
            getRepositories: () => deps.config.repositories,
            claudeInvokerDeps,
            gateClaudeInvocation,
            removeWorktree: removeWorktreeAction,
            recordBypass: new RecordBypassUseCase(trackingGw),
            noteCommentPostGateway: new GitLabNoteCommentPostCliGateway(defaultGitLabExecutor),
            handlePlatformApproval: new HandlePlatformApprovalUseCase(trackingGw),
            approvalRevocationGateway: new GitLabApprovalRevocationCliGateway(defaultGitLabExecutor),
            getQualityThreshold: (projectPath) => loadProjectConfig(projectPath)?.qualityThreshold ?? null,
            now: () => new Date().toISOString(),
        });
    });
    const gitHubThreadFetchGw = new GitHubThreadFetchGateway(defaultGitHubExecutor);
    app.post('/webhooks/github', async (request, reply) => {
        await handleGitHubWebhook(request, reply, deps.logger, trackingGw, {
            reviewContextGateway: deps.reviewContextGateway,
            threadFetchGateway: gitHubThreadFetchGw,
            diffMetadataFetchGateway: new GitHubDiffMetadataFetchGateway(defaultGitHubExecutor),
            diffStatsFetchGateway: new GitHubDiffStatsFetchGateway(defaultGitHubExecutor),
            trackAssignment: new TrackAssignmentUseCase(trackingGw),
            recordCompletion: new RecordReviewCompletionUseCase(trackingGw),
            recordPush: new RecordPushUseCase(trackingGw),
            transitionState: new TransitionStateUseCase(trackingGw),
            checkFollowupNeeded: new CheckFollowupNeededUseCase(trackingGw),
            syncThreads: new SyncThreadsUseCase(trackingGw, gitHubThreadFetchGw),
            enforceBudget,
            broadcastBudgetExceeded,
            getRepositories: () => deps.config.repositories,
            claudeInvokerDeps,
            gateClaudeInvocation,
            removeWorktree: removeWorktreeAction,
            recordBypass: new RecordBypassUseCase(trackingGw),
            noteCommentPostGateway: new GitHubNoteCommentPostCliGateway(defaultGitHubExecutor),
            handlePlatformApproval: new HandlePlatformApprovalUseCase(trackingGw),
            approvalRevocationGateway: new GitHubApprovalRevocationCliGateway(defaultGitHubExecutor),
            getQualityThreshold: (projectPath) => loadProjectConfig(projectPath)?.qualityThreshold ?? null,
            now: () => new Date().toISOString(),
        });
    });
    app.get('/', async (_request, reply) => {
        reply.redirect('/dashboard/');
    });
    await app.register(setupWizardRoutes, {
        registry: new SetupRunRegistry(new SetupProcessChildProcessGateway({ cliPath: join(__dirname, 'cli.js') })),
        setupStateGateway: new SetupStateFileSystemGateway({
            filePath: join(getConfigDir(), 'setup-state.json'),
        }),
        logger: deps.logger,
    });
    app.get('/setup', async (_request, reply) => {
        reply.redirect('/dashboard/setup.html');
    });
    const emberGroundingProjectPath = deps.config.repositories.find((repository) => repository.enabled)?.localPath ?? '';
    const emberReadData = new EmberReadDataCompositeGateway({
        statsGateway: deps.statsGateway,
        insightsGateway: deps.insightsGateway,
        trackingGateway: deps.reviewRequestTrackingGateway,
        worktreeGateway: deps.worktreeGateway,
    });
    const emberAnswerTransport = new EmberAnswerTransportClaudeGateway(new ClaudeSessionCliGateway(defaultProcessRunner()), { homeDir: homedir() });
    await app.register(emberChatRoutes, {
        transport: emberAnswerTransport,
        environment: new ProcessEnvironmentGateway(),
        readData: emberReadData,
        projectPath: emberGroundingProjectPath,
        logger: deps.logger,
    });
    const repositoryConfigDeps = { readFileSync, writeFileSync, existsSync };
    const addRepositoriesToConfig = new AddRepositoriesToConfigUseCase(repositoryConfigDeps);
    const removeRepositoryFromConfig = new RemoveRepositoryFromConfigUseCase(repositoryConfigDeps);
    const toggleRepositoryEnabled = new ToggleRepositoryEnabledUseCase(repositoryConfigDeps);
    const repositoriesConfigPath = resolveActiveConfigPath();
    function isExistingDirectory(path) {
        try {
            return statSync(path).isDirectory();
        }
        catch {
            return false;
        }
    }
    const addRepositoryFromDashboard = new AddRepositoryFromDashboardUseCase({
        isDirectory: isExistingDirectory,
        addRepositoriesToConfig,
        enrichSingleRepository,
        repositories: deps.config.repositories,
        configPath: repositoriesConfigPath,
    });
    const removeRepositoryFromDashboard = new RemoveRepositoryFromDashboardUseCase({
        removeRepositoryFromConfig,
        repositories: deps.config.repositories,
        configPath: repositoriesConfigPath,
    });
    const updateRepositoryEnabledFromDashboard = new UpdateRepositoryEnabledFromDashboardUseCase({
        toggleRepositoryEnabled,
        repositories: deps.config.repositories,
        configPath: repositoriesConfigPath,
    });
    await app.register(repositoriesRoutes, {
        getRepositories: () => deps.config.repositories,
        addRepository: (input) => addRepositoryFromDashboard.execute(input),
        removeRepository: (input) => removeRepositoryFromDashboard.execute(input),
        patchRepository: (input) => updateRepositoryEnabledFromDashboard.execute(input),
    });
    app.get('/api', async () => {
        return {
            name: 'reviewflow',
            version: currentVersion,
            endpoints: {
                dashboard: '/dashboard/',
                health: '/health',
                status: '/api/status',
                gitlab: '/webhooks/gitlab',
                github: '/webhooks/github',
            },
        };
    });
    checkVersion({ currentVersion, forceRefresh: false }, { packageVersionGateway, cache: versionCache, installTypeDetector }).catch(() => { });
}
//# sourceMappingURL=routes.js.map