import { IResolve } from "./app-paths";
import { QuasarConf, ResolvedQuasarConfValue } from "./configuration/conf";
import { QuasarContext } from "./configuration/context";
import { BuildOptions as EsbuildConfiguration } from "esbuild";

type ExtendViteConfHandler = (
  fn: (
    ...args: [...Parameters<ResolvedQuasarConfValue<"build.extendViteConf">>, api: IndexAPI]
  ) => void
) => void;

type GetPersistentConfHandler = () => Record<string, unknown>;
type HasExtensionHandler = (extId: string) => boolean;

interface BaseAPI {
  engine: '@quasar/app-vite';

  ctx: QuasarContext;
  extId: string;
  resolve: IResolve;
  appDir: string;

  hasVite: true;
  hasWebpack: false;

  hasTypescript: () => Promise<boolean>;
  hasLint: () => Promise<boolean>;
  getStorePackageName: () => 'pinia' | undefined;
  getNodePackagerName: () => Promise<'npm' | 'yarn' | 'pnpm' | 'bun'>;
}

interface SharedIndexInstallAPI {
  getPersistentConf: GetPersistentConfHandler;
  setPersistentConf: (cfg: Record<string, unknown>) => void;
  mergePersistentConf: (cfg: Record<string, unknown>) => void;
  compatibleWith: (packageName: string, semverCondition?: string) => void;
  hasPackage: (packageName: string, semverCondition?: string) => boolean;
  hasExtension: HasExtensionHandler;
  getPackageVersion: (packageName: string) => string | undefined;
}

type Callback<T> = (callback: T) => void;

export interface IndexAPI extends BaseAPI, SharedIndexInstallAPI {
  prompts: Record<string, unknown>;

  extendQuasarConf: Callback<(cfg: QuasarConf, api: IndexAPI) => void>;

  extendViteConf: ExtendViteConfHandler;

  extendBexScriptsConf: Callback<(cfg: EsbuildConfiguration, api: IndexAPI) => void>;
  extendElectronMainConf: Callback<(cfg: EsbuildConfiguration, api: IndexAPI) => void>;
  extendElectronPreloadConf: Callback<(cfg: EsbuildConfiguration, api: IndexAPI) => void>;
  extendPWACustomSWConf: Callback<(cfg: EsbuildConfiguration, api: IndexAPI) => void>;
  extendSSRWebserverConf: Callback<(cfg: EsbuildConfiguration, api: IndexAPI) => void>;

  registerCommand: (
    commandName: string,
    fn: (params: { args: string[]; params: Record<string, any> }) => Promise<void> | void
  ) => void;

  registerDescribeApi: (name: string, relativePath: string) => void;

  beforeDev: Callback<(
    api: IndexAPI,
    payload: { quasarConf: QuasarConf }
  ) => Promise<void> | void>;
  afterDev: Callback<(
    api: IndexAPI,
    payload: { quasarConf: QuasarConf }
  ) => Promise<void> | void>;
  beforeBuild: Callback<(
    api: IndexAPI,
    payload: { quasarConf: QuasarConf }
  ) => Promise<void> | void>;
  afterBuild: Callback<(
    api: IndexAPI,
    payload: { quasarConf: QuasarConf }
  ) => Promise<void> | void>;
  onPublish: Callback<(
    api: IndexAPI,
    opts: { arg: string; distDir: string }
  ) => Promise<void> | void>;
}

type ExitLogHandler = (msg: string) => void;
export interface InstallAPI extends BaseAPI, SharedIndexInstallAPI {
  prompts: Record<string, unknown>;

  extendPackageJson: (extPkg: object | string) => void;
  extendJsonFile: (file: string, newData: object) => void;
  render: (templatePath: string, scope?: object) => void;
  renderFile: (
    relativeSourcePath: string,
    relativeTargetPath: string,
    scope?: object
  ) => void;
  onExitLog: ExitLogHandler;
}

export interface UninstallAPI extends BaseAPI {
  prompts: Record<string, unknown>;

  getPersistentConf: GetPersistentConfHandler;
  hasExtension: HasExtensionHandler;
  removePath: (__path: string) => void;
  onExitLog: ExitLogHandler;
}

export interface PromptsAPI extends BaseAPI {
  compatibleWith: (packageName: string, semverCondition?: string) => void;
  hasPackage: (packageName: string, semverCondition?: string) => boolean;
  hasExtension: HasExtensionHandler;
  getPackageVersion: (packageName: string) => string | undefined;
}
