/**
 * Copyright IBM Corp. 2024, 2025
 */

import { APICProject } from '../../apic-mode/models/apic-project.model.js';
import { Response } from '../../common/models/response-wrapper.js';
import { PinnedProject } from '../../lfs/models/pinned-project.model.js';
import { Project } from '../../lfs/models/project.model.js';
import { RootDirectoryInfo } from '../../lfs/models/root-directory-info.model.js';
import { VCSProject } from '../../vcs/models/vcs-project.model.js';
import { ProjectDuplicateRequest } from '../models/project-operations.model.js';

export interface IProjectsHandler {
  /**
   * Loads all local projects and its corresponding assets from the configured root directories and returns as a list of project objects
   *
   * @returns A promise of list of projects wrapped in the response-wrapper
   */
  loadAllProjects(): Promise<Response<Project[]>>;
  /**
   * Loads all local projects and its corresponding assets from the given root directory and returns as a list of project objects
   *
   * @param parentFolder The root directory info / repository data to load projects from
   * @returns A promise of list of projects wrapped in the response-wrapper
   */
  loadProjectsForParentsFolder(
    parentFolder: RootDirectoryInfo,
  ): Promise<Response<Project[]>>;
  /**
   * Loads all local projects and its corresponding assets from the given root directory and returns as a list of project objects
   *
   * @param parentFolder The root directory info / repository data to load projects from
   * @returns A promise of list of projects wrapped in the response-wrapper
   */
  loadProjectsForParentsFolders(
    parentFolders: RootDirectoryInfo[],
  ): Promise<Response<Project[]>>;
  /**
   * Creates a new project entry in studio meta data file, returns the updated list of projects to use in store
   * @param newProject New project object
   * @returns A promise of updated list of projects wrapped in response-wrapper to use in store
   */
  createNewProject(
    newProject: Project,
    fileList?: File[],
  ): Promise<Response<Project>>;
  /**
   * Returns a list of projects by filtering based on the parent folder name
   * @param projects List of projects to filter from
   * @param uniqueParentFolderName Unique parent folder name to filter projects with, which could be either a repository name or a root directory alias
   * @returns A list of filtered projects
   */
  filterProjectsByUniqueParentFolderName(
    projects: (Project | VCSProject | APICProject)[],
    uniqueParentFolderName: string,
  ): (Project | VCSProject | APICProject)[];
  /**
   * Reloads all assets present in local project folder into the project argument.
   * @param project Project object to be refreshed
   * @returns A Promise of reloaded project with updated assets as per local project folder.
   */
  refreshProject(project: Project): Promise<Response<Project>>;
  /**
   * Checks and returns the given project as a VCSProject
   * @param project Local or VCS Project type
   * @returns A boolean to indicate whether the project is Local or VCS project, in addition it also informs ts compiler to treat project as VCS project if return type is true.
   */
  isVCSProject(
    project: Project | VCSProject | APICProject,
  ): project is VCSProject;
  /**
   * Returns the mode of the given project (local, vcs, or apic)
   * @param project Project object to determine the mode for
   * @returns A string representing the project mode
   */
  getProjectMode(project: Project | VCSProject | APICProject): string;
  /**
   * Checks whether the given project is already present in project list.
   * @param existingProjectList Existing list of projects from store
   * @param rootDirectoryAlias Unique label for the root directory / repository.
   * @param projectName Name of the project to be searched for duplication
   * @returns A boolean to indicate whether the project is duplicate or not.
   */
  isDuplicateProject(
    existingProjectList: (Project | VCSProject | APICProject)[],
    rootDirectoryAlias: string,
    projectName: string,
  ): boolean;
  /**
   * Searches through the project list and returns the index of specified project.
   * @param projects List of Local or VCS projects.
   * @param rootDirectoryAlias Unique label for the root directory / repository.
   * @param projectName Name of the project to be searched.
   * @returns Index of the first element in the projects list which matches with provided projectName and rootDirectoryAlias.
   * Returns -1 if no match is found.
   */
  findProjectIndex(
    projects: (Project | VCSProject | APICProject)[],
    rootDirectoryAlias: string,
    projectName: string,
  ): number;
  /**
   * Sorts the projects based on pinned projects.
   * @param pinnedProjects List of pinned projects
   * @param projects List of projects
   * @returns Sorted list of projects
   */
  getSortedProjects(
    pinnedProjects: PinnedProject[],
    projects: (Project | VCSProject | APICProject)[],
    sortColumn: string | null,
    sortOrder: 'asc' | 'desc',
  ): (Project | VCSProject)[];
  /**
   * Filters and returns the list of projects after removing projects belonging to any of the given parent folders
   * @param parentFolders The parent folder aliases for which the projects are to be deleted
   * @param projects List of all projects
   * @returns List of projects that do not belong to any of the given parents folders
   */
  removeProjectsByParentFolders(
    parentFolderAlias: string[],
    projects: (Project | VCSProject | APICProject)[],
  ): (Project | VCSProject | APICProject)[];
  /**
   * Identifies whether the project is local, vcs, or apic and orchestrates the flow accordingly to update the project
   * @param existingProject The original version of project
   * @param updatedProject Project with updated metadata
   */
  updateProject(
    existingProject: Project | VCSProject | APICProject,
    updatedProject: Project | VCSProject | APICProject,
  ): Promise<void>;
  /**
   * Identifes whether the project is local or vcs and orchestrates the flow accordingly to delete the projects
   * @param projects List of projects to be deleted
   */
  deleteProjects(projects: (Project | VCSProject)[]): Promise<void>;
  /**
   * Identifes whether the project is local or vcs and orchestrates the flow accordingly to duplicate the projects
   * @param duplicateRequestData Contains details aboout project source to be duplicated and target destination
   * @param newProjectName A unique project name for duplicated project
   */
  duplicateProject(
    duplicateRequestData: ProjectDuplicateRequest,
    newProjectName: string,
  ): Promise<Response<Project | VCSProject>>;
  /**
   * Generates a unique project name for duplicate project creation
   * @param name Current project name
   * @param projectList List of existing projects
   * @returns Newly generated unique project name
   */
  generateUniqueProjectName(
    name: string,
    projectList: (Project | VCSProject | APICProject)[],
  ): string;
}

export type ProjectType = Project | APICProject | VCSProject;