import type { Logger } from "pino";
import type { RepoConfig } from "@/types/index.js";
import { collectGithubMergedPrs } from "./github-metrics.js";
import { weekBucketsBetween } from "./week-buckets.js";
import type { AnalyticsReport } from "./types.js";

const DEFAULT_TIMEZONE = "America/New_York";

export interface CollectAnalyticsDeps {
  logger: Logger;
  /** Managed repos to scan for merged PRs (usually `RepoRegistry.getAll()`). */
  repos: readonly RepoConfig[];
  /** Returns a usable GitHub token (PAT or fresh GitHub App installation token). */
  getGitHubToken: () => Promise<string>;
  /** GitHub login of the bot — PRs with this author count as `prsMergedBot`. */
  botLogin: string;
  /**
   * Hard start date for the analytics window. Exactly one of `startDate` or
   * `maxWeeks` must be provided — the CLI surfaces this as `--from` / `--weeks`.
   */
  startDate?: Date;
  /** Alternative: restrict the window to the last N weeks (ending at `now`). */
  maxWeeks?: number;
  /** IANA timezone for week anchoring. Defaults to America/New_York. */
  timezone?: string;
  /** Clock override for tests. Defaults to `new Date()`. */
  now?: Date;
}

/**
 * Orchestrates the weekly GitHub PR-merged scan and wraps it into an
 * `AnalyticsReport`. Caller must provide either `startDate` or `maxWeeks`.
 */
export async function collectAnalytics(deps: CollectAnalyticsDeps): Promise<AnalyticsReport> {
  const {
    logger,
    repos,
    getGitHubToken,
    botLogin,
    startDate,
    maxWeeks,
    timezone = DEFAULT_TIMEZONE,
    now = new Date(),
  } = deps;

  if (!startDate && (!maxWeeks || maxWeeks <= 0)) {
    throw new Error(
      "collectAnalytics: pass `startDate` (CLI `--from YYYY-MM-DD`) or `maxWeeks` (CLI `--weeks N`).",
    );
  }

  const effectiveStart =
    startDate ?? new Date(now.getTime() - (maxWeeks ?? 0) * 7 * 24 * 60 * 60 * 1000);

  const buckets = weekBucketsBetween(effectiveStart, now, timezone);
  logger.info(
    {
      startDate: effectiveStart.toISOString(),
      endDate: now.toISOString(),
      weeks: buckets.length,
      timezone,
      repos: repos.length,
      botLogin,
    },
    "analytics_collect_start",
  );

  const github = await collectGithubMergedPrs({
    repos,
    getGitHubToken,
    botLogin,
    buckets,
    logger,
  });

  return {
    meta: {
      startDate: buckets[0]?.weekStart ?? effectiveStart.toISOString().slice(0, 10),
      generatedAt: now.toISOString(),
      timezone,
      botLogin,
      reposScanned: repos.length,
    },
    weekly: github.weekly,
    byRepo: github.byRepo,
    bySquad: github.bySquad,
  };
}
