// SPEC: PJ2026-01060703 CI/CD branch follower shared types.
// Responsibility: type contracts shared by branch follower entry, controller render, and native K8s helpers.

export type OutputMode = "human" | "json" | "yaml";
export type BranchFollowerAction = "help" | "plan" | "apply" | "status" | "run-once" | "debug-step" | "cleanup-state" | "events" | "logs" | "taskrun" | "job" | "runtime" | "gate";
export type BranchFollowerScope = "default" | "legacy-cicd" | "retired-maintenance";
export type BranchFollowerDeclaredDeliveryAuthority = "retired-readonly" | "legacy-manual" | "unknown";
export type BranchFollowerDebugStep = "state-read" | "controller-source" | "status-read" | "decide" | "state-write";
export type BranchFollowerGate = "reuse-plan" | "ci-taskrun-plan" | "cd-rollout-plan" | "post-deploy-health" | "control-plane-refresh" | "git-mirror-flush" | "runtime-closeout";
export type BranchFollowerPhase =
  | "Observed"
  | "Noop"
  | "PendingTrigger"
  | "Triggering"
  | "ClosingOut"
  | "Succeeded"
  | "Failed"
  | "Superseded"
  | "Blocked"
  | "Skipped";

export interface ParsedOptions {
  action: BranchFollowerAction;
  scope: BranchFollowerScope;
  configPath: string;
  followerId: string | null;
  all: boolean;
  confirm: boolean;
  dryRun: boolean;
  wait: boolean;
  inCluster: boolean;
  live: boolean;
  noLive: boolean;
  full: boolean;
  raw: boolean;
  recordState: boolean;
  debugStep: BranchFollowerDebugStep | null;
  gate: BranchFollowerGate | null;
  taskRunName: string | null;
  pipelineRunName: string | null;
  jobName: string | null;
  sourceCommit: string | null;
  workloadName: string | null;
  logsTailLines: number | null;
  maxLogBytes: number | null;
  output: OutputMode;
  limit: number;
  tailBytes: number;
  timeoutSeconds: number | null;
}

export interface CommandSpec {
  argv: string[];
  timeoutSeconds: number;
}

export interface FollowerSpec {
  id: string;
  enabled: boolean;
  deliveryAuthority: BranchFollowerDeclaredDeliveryAuthority;
  adapter: string;
  description: string;
  source: {
    repository: string;
    branch: string;
    branchRef: string;
    authorityRef: string;
    snapshotPrefix: string;
    snapshotRef: string;
  };
  target: {
    node: string;
    lane: string;
    namespace: string;
    sentinel: string | null;
    configRefs: Record<string, string>;
  };
  budgets: {
    endToEndSeconds: number;
    statusSeconds: number;
    triggerSeconds: number;
    sourceSyncSeconds: number;
    controlPlaneRefreshSeconds: number;
    capabilityJobTtlSeconds: number;
    capabilityJobBackoffLimit: number;
  };
  commands: {
    plan: CommandSpec;
    status: CommandSpec;
    trigger: CommandSpec;
    events: CommandSpec;
    logs: CommandSpec;
  };
  nativeStatus: NativeStatusSpec;
  drillDown: {
    taskRunTimeoutSeconds: number;
    logsTailLines: number;
    maxLogBytes: number;
    maxMessageBytes: number;
    maxContainers: number;
  } | null;
  closeoutChecks: string[];
}

export interface NativeStatusSpec {
  source: {
    gitMirrorReadUrl: string;
    gitMirrorNamespace: string;
    gitMirrorDeployment: string;
    repoPath: string;
  };
  tekton: {
    namespace: string;
    pipelineRunPrefix: string;
  } | null;
  argo: {
    namespace: string;
    application: string;
  } | null;
  runtime: {
    namespace: string;
    workloads: NativeWorkloadSpec[];
  } | null;
}

export interface NativeWorkloadSpec {
  kind: "Deployment" | "StatefulSet";
  name: string;
  sourceCommit: {
    labels: string[];
    annotations: string[];
    podLabels: string[];
    podAnnotations: string[];
    env: string[];
  };
}

export interface ControllerSpec {
  namespace: string;
  kubeRoute: string;
  fieldManager: string;
  serviceAccountName: string;
  deploymentName: string;
  configMapName: string;
  stateConfigMapName: string;
  leaseName: string;
  image: string;
  labels: Record<string, string>;
  source: {
    repository: string;
    branch: string;
    gitMirrorReadUrl: string;
    gitMirrorCachePvcName: string;
    githubSsh: {
      secretName: string;
      privateKeySecretKey: string;
      proxyHost: string;
      proxyPort: number;
    };
    sourceAuthority: {
      mode: string;
      resolver: string;
      allowHostGit: boolean;
      allowHostWorkspace: boolean;
      allowGithubDirectInPipeline: boolean;
    };
    sourceSnapshot: {
      stageRefPrefix: string;
      missingObjectPolicy: string;
      refreshPolicy: string;
    };
  };
  loop: {
    intervalSeconds: number;
    reconcileTimeoutSeconds: number;
    leaseDurationSeconds: number;
    terminationGracePeriodSeconds: number;
  };
  budgets: {
    applyWaitSeconds: number;
    statusSeconds: number;
    runOnceSeconds: number;
    reconcileJobTtlSeconds: number;
    reconcileJobBackoffLimit: number;
    reconcileJobDeadlineGraceSeconds: number;
    reconcileTransportGraceSeconds: number;
    nativeTransportGraceSeconds: number;
    nativePollIntervalSeconds: number;
  };
}

export interface BranchFollowerRegistry {
  path: string;
  rawText: string;
  rawSha256: string;
  metadata: {
    id: string;
    owner: string;
    specRef: string;
    version: string;
  };
  controller: ControllerSpec;
  followers: FollowerSpec[];
}

export interface AdapterSummary {
  ok: boolean;
  command: string;
  exitCode: number | null;
  timedOut: boolean;
  observedSha: string | null;
  targetSha: string | null;
  lastTriggeredSha: string | null;
  lastSucceededSha: string | null;
  pipelineRun: string | null;
  pipelineRunPresent: boolean | null;
  inFlightJob: string | null;
  aligned: boolean | null;
  phase: BranchFollowerPhase;
  message: string;
  payload: Record<string, unknown> | null;
  stderrTail: string;
  stdoutTail: string;
}

export interface NativeObjectBundle {
  ok: boolean;
  source: Record<string, unknown> | null;
  gitMirror: Record<string, unknown> | null;
  pipelineRun: Record<string, unknown> | null;
  pipeline: Record<string, unknown> | null;
  taskRuns: Record<string, unknown> | null;
  planArtifacts: Record<string, unknown> | null;
  argoApplication: Record<string, unknown> | null;
  workloads: Record<string, unknown>[];
  errors: string[];
  exitCode: number | null;
  timedOut: boolean;
  elapsedMs: number;
  stdoutTail: string;
  stderrTail: string;
}

export interface TriggerResult {
  ok: boolean;
  completed: boolean;
  message: string;
  jobId: string | null;
  command: Record<string, unknown>;
}

export interface NativeCloseoutWaitResult {
  ok: boolean;
  completed: boolean;
  timedOut: boolean;
  polls: number;
  elapsedMs: number;
  refresh: Record<string, unknown> | null;
  gitMirrorFlush: Record<string, unknown> | null;
  summary: Record<string, unknown> | null;
  statusAuthority: "k8s-native";
  parsedDownstreamCliOutput: false;
}

export interface NativeK8sJobResult {
  ok: boolean;
  completed: boolean;
  failed: boolean;
  timedOut: boolean;
  created: boolean;
  reused: boolean;
  jobName: string;
  namespace: string;
  polls: number;
  elapsedMs: number;
  startedAt: string | null;
  finishedAt: string | null;
  logsTail: string | null;
  summary: Record<string, unknown> | null;
  conditionReason: string | null;
  conditionMessage: string | null;
  statusAuthority: "kubernetes-api-serviceaccount";
  parsedDownstreamCliOutput: false;
}

export interface StageTiming {
  stage: string;
  status: string;
  seconds: number | null;
  budgetSeconds: number | null;
  source: string;
  object: string | null;
  startedAt?: string | null;
  finishedAt?: string | null;
}

export interface FollowerState {
  id: string;
  adapter: string;
  enabled: boolean;
  phase: BranchFollowerPhase;
  source: {
    repository: string;
    branch: string;
    branchRef: string;
    snapshotPrefix: string;
    observedSha: string | null;
  };
  target: {
    node: string;
    lane: string;
    namespace: string;
    sentinel: string | null;
    targetSha: string | null;
  };
  lastTriggeredSha: string | null;
  lastSucceededSha: string | null;
  pipelineRun: string | null;
  inFlightJob: string | null;
  budgetSource: Record<string, number>;
  controller: {
    mode: "local-cli" | "k8s-controller";
    stateConfigMap: string;
    leaseName: string;
  };
  decision: string;
  dryRun: boolean;
  updatedAt: string;
  timings: {
    budgetSeconds: number;
    totalSeconds: number | null;
    totalStatus: string;
    totalSource: string;
    sourceCommit: string | null;
    startedAt: string | null;
    finishedAt: string | null;
    overBudget: boolean | null;
    stages: StageTiming[];
  };
  warnings: string[];
  next: Record<string, string>;
  command?: Record<string, unknown>;
}

export interface K8sStateRead {
  ok: boolean;
  stateByFollower: Record<string, Record<string, unknown>>;
  stateMetadata: Record<string, unknown> | null;
  stateValueBytes: Record<string, number>;
  stateConfigMapPresent: boolean;
  deployment: Record<string, unknown> | null;
  lease: Record<string, unknown> | null;
  pods: Record<string, unknown> | null;
  errors: string[];
  warnings: string[];
}

export interface K8sFollowerStateRead {
  ok: boolean;
  stateByFollower: Record<string, Record<string, unknown>>;
  metadata: Record<string, unknown> | null;
  valueBytes: Record<string, number>;
  present: boolean;
  error: string;
}
