import type { ProjectFilePath } from '@learnitive/project-storage';
import type { ProjectGitDiff } from './diff';

export type GitChangeKind =
  | 'added'
  | 'modified'
  | 'deleted'
  | 'untracked'
  | 'conflicted';

export type ProjectGitFileChange = {
  path: ProjectFilePath;
  status: GitChangeKind;
  staged: boolean;
};

export type ProjectGitCommit = {
  oid: string;
  message: string;
  authorName: string;
  authorEmail: string;
  timestamp: number;
  parents: readonly string[];
};

export type ProjectGitRemote = {
  remote: string;
  url: string;
};

export type ProjectGitStatus = {
  branch?: string;
  staged: readonly ProjectGitFileChange[];
  unstaged: readonly ProjectGitFileChange[];
};

/**
 * Learnitive-facing Git engine contract. Browser implementation details such as
 * LightningFS and Git HTTP stay behind this boundary so editor/project layers
 * only deal in project paths and explicit operations.
 */
export interface ProjectGitEngine {
  readonly available: boolean;

  init(defaultBranch?: string): Promise<void>;
  clone(
    url: string,
    input?: { token?: string; corsProxy?: string; singleBranch?: boolean },
  ): Promise<void>;
  isRepository(): Promise<boolean>;
  status(): Promise<ProjectGitStatus>;
  diff(path: ProjectFilePath): Promise<ProjectGitDiff>;
  stage(paths: readonly ProjectFilePath[]): Promise<void>;
  unstage(paths: readonly ProjectFilePath[]): Promise<void>;
  commit(input: {
    message: string;
    authorName: string;
    authorEmail: string;
  }): Promise<string>;
  log(depth?: number): Promise<readonly ProjectGitCommit[]>;
  listBranches(): Promise<readonly string[]>;
  createBranch(name: string): Promise<void>;
  deleteBranch(name: string): Promise<void>;
  checkout(branch: string): Promise<void>;
  merge(
    branch: string,
    author?: { name: string; email: string },
  ): Promise<{ oid?: string; conflicts: readonly string[] }>;
  listRemotes(): Promise<readonly ProjectGitRemote[]>;
  addRemote(name: string, url: string): Promise<void>;
  removeRemote(name: string): Promise<void>;
  fetch(input?: {
    remote?: string;
    token?: string;
    corsProxy?: string;
  }): Promise<void>;
  pull(input?: {
    remote?: string;
    token?: string;
    corsProxy?: string;
    author?: { name: string; email: string };
  }): Promise<void>;
  push(input?: {
    remote?: string;
    token?: string;
    corsProxy?: string;
  }): Promise<void>;
  /** Remove browser-local Git object/index state for a deleted Learnitive project. */
  discardLocalRepository(): Promise<void>;
}
