/**
 * squash-base.ts — Pure resolver for the squash/rebase "reference branch".
 *
 * Ported verbatim from the 4.x EF Core agent GOLDEN RULE
 * (`templates/agents/efcore/squash.md` @ v4.81.0):
 *
 *   feature/* → snapshot + migrations from develop   (feature → develop)
 *   develop   → snapshot + migrations from main       (develop → prod)
 *   release/* → snapshot + migrations from main       (release → prod)
 *   hotfix/*  → snapshot + migrations from main        (hotfix  → prod)
 *   main      → BLOCKED (never squash on production)
 *   <other>   → develop (4.x default)
 *
 * The base branch is the **merge target** — the branch whose migrations are
 * already shared / applied downstream. A squash may NEVER delete a migration
 * that lives in this reference branch; it only consolidates the migrations
 * that are unique to the current branch.
 *
 * The v5 rewrite lost this mapping and always preferred `develop` regardless
 * of the branch type, so a release/hotfix (whose true reference is `main`)
 * could delete migrations that already exist in production. This restores the
 * 4.x rule.
 */

export type SquashBranchType = 'feature' | 'release' | 'hotfix' | 'develop' | 'main' | 'unknown';

export interface BranchNames {
  /** Production branch name. Default `main`. */
  main?: string;
  /** Integration branch name. Default `develop`. */
  develop?: string;
}

export interface BaseDecision {
  branchType: SquashBranchType;
  /** The reference branch to diff / restore against. `null` when blocked. */
  baseBranch: string | null;
  /** True for main / master — squash and rebase must refuse. */
  blocked: boolean;
  /** Human-readable justification (shown to the user before any deletion). */
  reason: string;
}

/**
 * Resolve the reference branch for a squash, by branch *type* — never by a
 * blind "develop first" fallback. Mirrors the 4.x `determine_base_branch`.
 */
export function determineBaseBranch(currentBranch: string, names: BranchNames = {}): BaseDecision {
  const main = names.main ?? 'main';
  const develop = names.develop ?? 'develop';
  const branch = (currentBranch ?? '').trim();
  const lower = branch.toLowerCase();

  // Production branches — never squashable.
  if (lower === 'main' || lower === 'master' || lower === main.toLowerCase()) {
    return {
      branchType: 'main',
      baseBranch: null,
      blocked: true,
      reason: `"${branch}" is a protected production branch — squashing migrations there would rewrite history already applied to prod.`,
    };
  }

  // develop integrates into main (develop → prod).
  if (lower === 'develop' || lower === develop.toLowerCase()) {
    return {
      branchType: 'develop',
      baseBranch: main,
      blocked: false,
      reason: `develop squashes onto "${main}" (develop → prod): only migrations not yet in ${main} may be consolidated.`,
    };
  }

  if (lower.startsWith('feature/')) {
    return {
      branchType: 'feature',
      baseBranch: develop,
      blocked: false,
      reason: `feature squashes onto "${develop}" (feature → develop): migrations already in ${develop} are preserved.`,
    };
  }

  if (lower.startsWith('release/')) {
    return {
      branchType: 'release',
      baseBranch: main,
      blocked: false,
      reason: `release squashes onto "${main}" (release → prod): migrations already in ${main} are preserved.`,
    };
  }

  if (lower.startsWith('hotfix/')) {
    return {
      branchType: 'hotfix',
      baseBranch: main,
      blocked: false,
      reason: `hotfix squashes onto "${main}" (hotfix → prod): migrations already in ${main} are preserved.`,
    };
  }

  // 4.x default for anything else: treat develop as the reference.
  return {
    branchType: 'unknown',
    baseBranch: develop,
    blocked: false,
    reason: `unknown branch type — defaulting the reference branch to "${develop}".`,
  };
}
