import type { AgentTaskCategoryCode } from '@ftb/shared'; type EstimateRange = { min: number; max: number; fallback: number }; const DEV_ESTIMATE_RANGES: Record = { frontend_development: { min: 0.25, max: 1, fallback: 0.5 }, frontend_interaction: { min: 0.25, max: 0.5, fallback: 0.25 }, backend_development: { min: 0.75, max: 2, fallback: 1.25 }, backend_api: { min: 0.5, max: 1, fallback: 0.75 }, database_schema: { min: 0.25, max: 0.5, fallback: 0.25 }, api_integration: { min: 0.5, max: 1.25, fallback: 0.75 }, data_processing: { min: 0.75, max: 1.5, fallback: 1 }, implementation_support: { min: 0.25, max: 1, fallback: 0.5 }, documentation: { min: 0.25, max: 0.5, fallback: 0.5 }, }; const TEST_ESTIMATE_RANGES: Record = { test_functional: { min: 0.1, max: 0.3, fallback: 0.2 }, test_ui_interaction: { min: 0.1, max: 0.3, fallback: 0.2 }, test_form_validation: { min: 0.1, max: 0.25, fallback: 0.2 }, test_api: { min: 0.2, max: 0.5, fallback: 0.3 }, test_data_consistency: { min: 0.2, max: 0.5, fallback: 0.3 }, test_permission: { min: 0.2, max: 0.5, fallback: 0.3 }, test_exception: { min: 0.2, max: 0.5, fallback: 0.3 }, test_boundary: { min: 0.1, max: 0.3, fallback: 0.2 }, test_state_flow: { min: 0.2, max: 0.5, fallback: 0.3 }, test_compatibility: { min: 0.3, max: 0.8, fallback: 0.4 }, test_regression: { min: 0.15, max: 0.4, fallback: 0.25 }, }; const EXECUTOR_TEST_ESTIMATE_RANGES: Record = { test_functional: { min: 0.25, max: 2, fallback: 0.5 }, test_ui_interaction: { min: 0.25, max: 2, fallback: 0.5 }, test_form_validation: { min: 0.25, max: 2, fallback: 0.5 }, test_api: { min: 0.25, max: 2, fallback: 0.5 }, test_data_consistency: { min: 0.25, max: 2, fallback: 0.5 }, test_permission: { min: 0.25, max: 2, fallback: 0.5 }, test_exception: { min: 0.25, max: 2, fallback: 0.5 }, test_boundary: { min: 0.25, max: 2, fallback: 0.5 }, test_state_flow: { min: 0.25, max: 2, fallback: 0.5 }, test_compatibility: { min: 0.25, max: 2, fallback: 0.5 }, test_regression: { min: 0.25, max: 2, fallback: 0.5 }, }; function roundToStep(hours: number, step: number): number { return Number((Math.round(hours / step) * step).toFixed(2)); } function clampToRange(raw: number | undefined, range: EstimateRange, step: number): number { const base = typeof raw === 'number' && Number.isFinite(raw) && raw > 0 ? raw : range.fallback; return roundToStep(Math.min(range.max, Math.max(range.min, base)), step); } export function clampDevAiEstimateHours(code: AgentTaskCategoryCode | string | undefined, raw: number | undefined): number { return clampToRange(raw, DEV_ESTIMATE_RANGES[code ?? ''] ?? { min: 0.25, max: 1.5, fallback: 0.75 }, 0.25); } export function getDefaultTestCaseAiEstimateHours(code: AgentTaskCategoryCode | string | undefined): number { return (TEST_ESTIMATE_RANGES[code ?? ''] ?? TEST_ESTIMATE_RANGES.test_functional).fallback; } export function clampTestCaseAiEstimateHours(code: AgentTaskCategoryCode | string | undefined, raw: number | undefined): number { return clampToRange(raw, TEST_ESTIMATE_RANGES[code ?? ''] ?? TEST_ESTIMATE_RANGES.test_functional, 0.1); } export const clampDevEstimateHours = clampDevAiEstimateHours; export function getDefaultTestCaseEstimateHours(code: AgentTaskCategoryCode | string | undefined): number { return (EXECUTOR_TEST_ESTIMATE_RANGES[code ?? ''] ?? EXECUTOR_TEST_ESTIMATE_RANGES.test_functional).fallback; } export function clampTestCaseEstimateHours(code: AgentTaskCategoryCode | string | undefined, raw: number | undefined): number { return clampToRange(raw, EXECUTOR_TEST_ESTIMATE_RANGES[code ?? ''] ?? EXECUTOR_TEST_ESTIMATE_RANGES.test_functional, 0.25); }