const CoolifyClient = require('../coolifyClient');

/**
 * List all applications.
 * @param {string} host_url - Coolify instance URL
 * @param {string} token - Bearer token
 * @returns {Promise<Object[]>}
 * @example
 * list('https://coolify.example.com', 'TOKEN');
 */
async function list(host_url, token) {
  const client = new CoolifyClient(host_url, token);
  return client.get('/api/v1/applications');
}

/**
 * Get application by UUID.
 * @param {string} host_url
 * @param {string} token
 * @param {string} uuid - Application UUID
 * @returns {Promise<Object>}
 * @example
 * get('https://coolify.example.com', 'TOKEN', 'app-uuid');
 */
async function get(host_url, token, uuid) {
  const client = new CoolifyClient(host_url, token);
  return client.get(`/api/v1/applications/${uuid}`);
}

/**
 * Create new application (public repo).
 * @param {string} host_url
 * @param {string} token
 * @param {Object} data - Application creation payload.
 * @param {string} data.project_uuid - The project UUID. (required)
 * @param {string} data.server_uuid - The server UUID. (required)
 * @param {string} data.environment_name - The environment name. (required, at least one of environment_name or environment_uuid)
 * @param {string} data.environment_uuid - The environment UUID. (required, at least one of environment_name or environment_uuid)
 * @param {string} data.git_repository - The git repository URL. (required)
 * @param {string} data.git_branch - The git branch. (required)
 * @param {string} data.build_pack - The build pack type. One of: 'nixpacks', 'static', 'dockerfile', 'dockercompose'. (required)
 * @param {string} data.ports_exposes - The ports to expose. (required)
 * @param {string} [data.destination_uuid] - The destination UUID.
 * @param {string} [data.name] - The application name.
 * @param {string} [data.description] - The application description.
 * @param {string} [data.domains] - The application domains.
 * @param {string} [data.git_commit_sha] - The git commit SHA.
 * @param {string} [data.docker_registry_image_name] - The docker registry image name.
 * @param {string} [data.docker_registry_image_tag] - The docker registry image tag.
 * @param {boolean} [data.is_static] - The flag to indicate if the application is static.
 * @param {string} [data.static_image] - The static image. Enum: ['nginx:alpine']
 * @param {string} [data.install_command] - The install command.
 * @param {string} [data.build_command] - The build command.
 * @param {string} [data.start_command] - The start command.
 * @param {string} [data.ports_mappings] - The ports mappings.
 * @param {string} [data.base_directory] - The base directory for all commands.
 * @param {string} [data.publish_directory] - The publish directory.
 * @param {boolean} [data.health_check_enabled] - Health check enabled.
 * @param {string} [data.health_check_path] - Health check path.
 * @param {string} [data.health_check_port] - Health check port.
 * @param {string} [data.health_check_host] - Health check host.
 * @param {string} [data.health_check_method] - Health check method.
 * @param {integer} [data.health_check_return_code] - Health check return code.
 * @param {string} [data.health_check_scheme] - Health check scheme.
 * @param {string} [data.health_check_response_text] - Health check response text.
 * @param {integer} [data.health_check_interval] - Health check interval in seconds.
 * @param {integer} [data.health_check_timeout] - Health check timeout in seconds.
 * @param {integer} [data.health_check_retries] - Health check retries count.
 * @param {integer} [data.health_check_start_period] - Health check start period in seconds.
 * @param {string} [data.limits_memory] - Memory limit.
 * @param {string} [data.limits_memory_swap] - Memory swap limit.
 * @param {integer} [data.limits_memory_swappiness] - Memory swappiness.
 * @param {string} [data.limits_memory_reservation] - Memory reservation.
 * @param {string} [data.limits_cpus] - CPU limit.
 * @param {string} [data.limits_cpuset] - CPU set.
 * @param {integer} [data.limits_cpu_shares] - CPU shares.
 * @param {string} [data.custom_labels] - Custom labels.
 * @param {string} [data.custom_docker_run_options] - Custom docker run options.
 * @param {string} [data.post_deployment_command] - Post deployment command.
 * @param {string} [data.post_deployment_command_container] - Post deployment command container.
 * @param {string} [data.pre_deployment_command] - Pre deployment command.
 * @param {string} [data.pre_deployment_command_container] - Pre deployment command container.
 * @param {string} [data.manual_webhook_secret_github] - Manual webhook secret for Github.
 * @param {string} [data.manual_webhook_secret_gitlab] - Manual webhook secret for Gitlab.
 * @param {string} [data.manual_webhook_secret_bitbucket] - Manual webhook secret for Bitbucket.
 * @param {string} [data.manual_webhook_secret_gitea] - Manual webhook secret for Gitea.
 * @param {string} [data.redirect] - How to set redirect with Traefik / Caddy. Enum: [www, non-www, both]
 * @param {boolean} [data.instant_deploy] - The flag to indicate if the application should be deployed instantly.
 * @param {string} [data.dockerfile] - The Dockerfile content.
 * @param {string} [data.docker_compose_location] - The Docker Compose location.
 * @param {string} [data.docker_compose_raw] - The Docker Compose raw content.
 * @param {string} [data.docker_compose_custom_start_command] - The Docker Compose custom start command.
 * @param {string} [data.docker_compose_custom_build_command] - The Docker Compose custom build command.
 * @param {array} [data.docker_compose_domains] - The Docker Compose domains.
 * @param {string} [data.watch_paths] - The watch paths.
 * @param {boolean} [data.use_build_server] - Use build server.
 * @returns {Promise<Object>}
 * @example
 * createPublic('https://coolify.example.com', 'TOKEN', {
 *   project_uuid: '123',
 *   server_uuid: '456',
 *   environment_name: 'production',
 *   environment_uuid: 'env-uuid',
 *   git_repository: 'https://github.com/user/repo.git',
 *   git_branch: 'main',
 *   build_pack: 'nixpacks',
 *   ports_exposes: '3000',
 *   name: 'My App',
 *   description: 'A sample app',
 *   // ...other optional fields
 * });
 */
async function createPublic(host_url, token, data) {
  const client = new CoolifyClient(host_url, token);
  return client.post('/api/v1/applications/public', data);
}

/**
 * Create new application (private GitHub app).
 * @param {string} host_url
 * @param {string} token
 * @param {Object} data - Application creation payload (see OpenAPI)
 * @returns {Promise<Object>}
 * @example
 * createPrivateGithubApp('https://coolify.example.com', 'TOKEN', { ... });
 */
async function createPrivateGithubApp(host_url, token, data) {
  const client = new CoolifyClient(host_url, token);
  return client.post('/api/v1/applications/private-github-app', data);
}

/**
 * Create new application (private deploy key).
 * @param {string} host_url
 * @param {string} token
 * @param {Object} data - Application creation payload (see OpenAPI)
 * @returns {Promise<Object>}
 * @example
 * createPrivateDeployKey('https://coolify.example.com', 'TOKEN', { ... });
 */
async function createPrivateDeployKey(host_url, token, data) {
  const client = new CoolifyClient(host_url, token);
  return client.post('/api/v1/applications/private-deploy-key', data);
}

/**
 * Create new application (Dockerfile).
 * @param {string} host_url
 * @param {string} token
 * @param {Object} data - Application creation payload (see OpenAPI)
 * @returns {Promise<Object>}
 * @example
 * createDockerfile('https://coolify.example.com', 'TOKEN', { ... });
 */
async function createDockerfile(host_url, token, data) {
  const client = new CoolifyClient(host_url, token);
  return client.post('/api/v1/applications/dockerfile', data);
}

/**
 * Create new application (Docker image).
 * @param {string} host_url
 * @param {string} token
 * @param {Object} data - Application creation payload (see OpenAPI)
 * @returns {Promise<Object>}
 * @example
 * createDockerimage('https://coolify.example.com', 'TOKEN', { ... });
 */
async function createDockerimage(host_url, token, data) {
  const client = new CoolifyClient(host_url, token);
  return client.post('/api/v1/applications/dockerimage', data);
}

/**
 * Create new application (Docker Compose).
 * @param {string} host_url
 * @param {string} token
 * @param {Object} data - Application creation payload (see OpenAPI)
 * @returns {Promise<Object>}
 * @example
 * createDockercompose('https://coolify.example.com', 'TOKEN', { ... });
 */
async function createDockercompose(host_url, token, data) {
  const client = new CoolifyClient(host_url, token);
  return client.post('/api/v1/applications/dockercompose', data);
}

/**
 * Update application by UUID.
 * @param {string} host_url
 * @param {string} token
 * @param {string} uuid - Application UUID
 * @param {Object} data - Update payload
 * @returns {Promise<Object>}
 * @example
 * update('https://coolify.example.com', 'TOKEN', 'app-uuid', { ... });
 */
async function update(host_url, token, uuid, data) {
  const client = new CoolifyClient(host_url, token);
  return client.patch(`/api/v1/applications/${uuid}`, data);
}

/**
 * Delete application by UUID.
 * @param {string} host_url
 * @param {string} token
 * @param {string} uuid - Application UUID
 * @param {Object} params - Optional query params (delete_configurations, delete_volumes, etc.)
 * @returns {Promise<Object>}
 * @example
 * remove('https://coolify.example.com', 'TOKEN', 'app-uuid', { delete_configurations: true });
 */
async function remove(host_url, token, uuid, params = {}) {
  const client = new CoolifyClient(host_url, token);
  return client.delete(`/api/v1/applications/${uuid}`, { params });
}

/**
 * List all envs by application UUID.
 * @param {string} host_url
 * @param {string} token
 * @param {string} uuid - Application UUID
 * @returns {Promise<Object[]>}
 * @example
 * listEnvs('https://coolify.example.com', 'TOKEN', 'app-uuid');
 */
async function listEnvs(host_url, token, uuid) {
  const client = new CoolifyClient(host_url, token);
  return client.get(`/api/v1/applications/${uuid}/envs`);
}

/**
 * Create env by application UUID.
 * @param {string} host_url
 * @param {string} token
 * @param {string} uuid - Application UUID
 * @param {Object} data - Env payload
 * @returns {Promise<Object>}
 * @example
 * createEnv('https://coolify.example.com', 'TOKEN', 'app-uuid', { key: 'FOO', value: 'bar' });
 */
async function createEnv(host_url, token, uuid, data) {
  const client = new CoolifyClient(host_url, token);
  return client.post(`/api/v1/applications/${uuid}/envs`, data);
}

/**
 * Update env by application UUID.
 * @param {string} host_url
 * @param {string} token
 * @param {string} uuid - Application UUID
 * @param {Object} data - Env update payload
 * @returns {Promise<Object>}
 * @example
 * updateEnv('https://coolify.example.com', 'TOKEN', 'app-uuid', { key: 'FOO', value: 'baz' });
 */
async function updateEnv(host_url, token, uuid, data) {
  const client = new CoolifyClient(host_url, token);
  return client.patch(`/api/v1/applications/${uuid}/envs`, data);
}

/**
 * Update multiple envs by application UUID (bulk).
 * @param {string} host_url
 * @param {string} token
 * @param {string} uuid - Application UUID
 * @param {Object} data - Bulk envs update payload
 * @returns {Promise<Object>}
 * @example
 * updateEnvsBulk('https://coolify.example.com', 'TOKEN', 'app-uuid', { data: [...] });
 */
async function updateEnvsBulk(host_url, token, uuid, data) {
  const client = new CoolifyClient(host_url, token);
  return client.patch(`/api/v1/applications/${uuid}/envs/bulk`, data);
}

/**
 * Delete env by UUID.
 * @param {string} host_url
 * @param {string} token
 * @param {string} uuid - Application UUID
 * @param {string} env_uuid - Env UUID
 * @returns {Promise<Object>}
 * @example
 * removeEnv('https://coolify.example.com', 'TOKEN', 'app-uuid', 'env-uuid');
 */
async function removeEnv(host_url, token, uuid, env_uuid) {
  const client = new CoolifyClient(host_url, token);
  return client.delete(`/api/v1/applications/${uuid}/envs/${env_uuid}`);
}

/**
 * Start application by UUID.
 * @param {string} host_url
 * @param {string} token
 * @param {string} uuid - Application UUID
 * @param {Object} params - Optional query params (force, instant_deploy)
 * @returns {Promise<Object>}
 * @example
 * start('https://coolify.example.com', 'TOKEN', 'app-uuid', { force: true });
 */
async function start(host_url, token, uuid, params = {}) {
  const client = new CoolifyClient(host_url, token);
  return client.get(`/api/v1/applications/${uuid}/start`, { params });
}

/**
 * Stop application by UUID.
 * @param {string} host_url
 * @param {string} token
 * @param {string} uuid - Application UUID
 * @returns {Promise<Object>}
 * @example
 * stop('https://coolify.example.com', 'TOKEN', 'app-uuid');
 */
async function stop(host_url, token, uuid) {
  const client = new CoolifyClient(host_url, token);
  return client.get(`/api/v1/applications/${uuid}/stop`);
}

/**
 * Restart application by UUID.
 * @param {string} host_url
 * @param {string} token
 * @param {string} uuid - Application UUID
 * @returns {Promise<Object>}
 * @example
 * restart('https://coolify.example.com', 'TOKEN', 'app-uuid');
 */
async function restart(host_url, token, uuid) {
  const client = new CoolifyClient(host_url, token);
  return client.get(`/api/v1/applications/${uuid}/restart`);
}

/**
 * Execute a command on the application's current container.
 * @param {string} host_url
 * @param {string} token
 * @param {string} uuid - Application UUID
 * @param {Object} data - { command: string }
 * @returns {Promise<Object>}
 * @example
 * execute('https://coolify.example.com', 'TOKEN', 'app-uuid', { command: 'ls -la' });
 */
async function execute(host_url, token, uuid, data) {
  const client = new CoolifyClient(host_url, token);
  return client.post(`/api/v1/applications/${uuid}/execute`, data);
}

module.exports = {
  list,
  get,
  createPublic,
  createPrivateGithubApp,
  createPrivateDeployKey,
  createDockerfile,
  createDockerimage,
  createDockercompose,
  update,
  remove,
  listEnvs,
  createEnv,
  updateEnv,
  updateEnvsBulk,
  removeEnv,
  start,
  stop,
  restart,
  execute,
}; 