import type { MetricsBucket, RuntimeMode, TargetMetricsResponse } from "../../shared/api";
import type { ProbeStore } from "../checker/store";

import { jsonResponse } from "../helpers";
import {
  analyzeIncidentSequence,
  buildTrend,
  calculateAverageDuration,
  calculateCurrentStreak,
  calculatePercentile,
  type MetricCheckpoint,
  resolveAutoBucket,
} from "../metrics";
import { validateMetricsBucket, validateTargetId, validateTimeRange } from "../middleware";

export function handleMetrics(idStr: string, url: URL, store: ProbeStore, mode: RuntimeMode): Response {
  const idResult = validateTargetId(idStr, mode);
  if (idResult instanceof Response) return idResult;

  const target = store.getTargetById(idResult.id);
  if (!target) {
    return jsonResponse({ error: "Target not found", status: 404 } as const, { mode, status: 404 });
  }

  const timeResult = validateTimeRange(url.searchParams.get("from"), url.searchParams.get("to"), mode);
  if (timeResult instanceof Response) return timeResult;

  const bucketResult = validateMetricsBucket(url.searchParams.get("bucket"), mode);
  if (bucketResult instanceof Response) return bucketResult;

  const requestedBucket = bucketResult.bucket;
  let resolvedBucket: MetricsBucket;
  if (requestedBucket === "auto") {
    const windowMs = new Date(timeResult.to).getTime() - new Date(timeResult.from).getTime();
    resolvedBucket = resolveAutoBucket(target.interval_ms, windowMs);
  } else {
    resolvedBucket = requestedBucket;
  }

  const checkpoints = store
    .getTargetCheckpoints(idResult.id, timeResult.from, timeResult.to)
    .map((checkpoint): MetricCheckpoint => {
      return {
        durationMs: checkpoint.duration_ms,
        matched: checkpoint.matched === 1,
        timestamp: checkpoint.timestamp,
      };
    });
  const durations = store.getTargetDurations(idResult.id, timeResult.from, timeResult.to);
  const stats = store.getTargetWindowStats(idResult.id, timeResult.from, timeResult.to);
  const incidentAnalysis = analyzeIncidentSequence(checkpoints, timeResult.from, timeResult.to);

  const response: TargetMetricsResponse = {
    stats: {
      availability: stats.availability,
      avgDurationMs: calculateAverageDuration(durations),
      currentStreak: calculateCurrentStreak(checkpoints),
      downChecks: stats.downChecks,
      incidentCount: incidentAnalysis.incidentCount,
      longestOutage: incidentAnalysis.longestOutage,
      mttr: incidentAnalysis.mttr,
      p95DurationMs: calculatePercentile(durations, 95),
      p99DurationMs: calculatePercentile(durations, 99),
      totalChecks: stats.totalChecks,
      upChecks: stats.upChecks,
    },
    targetId: idResult.id,
    trend: buildTrend(checkpoints, timeResult.from, timeResult.to, resolvedBucket),
    window: {
      bucket: resolvedBucket,
      from: timeResult.from,
      to: timeResult.to,
    },
  };

  return jsonResponse(response, { mode });
}
