import { HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
import { Schema } from "effect";
import {
  InternalError,
  ScopeId,
  SecretId,
  SecretInUseError,
  SecretNotFoundError,
  SecretOwnedByConnectionError,
  SecretResolutionError,
  Usage,
} from "@executor-js/sdk/shared";

// ---------------------------------------------------------------------------
// Params
// ---------------------------------------------------------------------------

const ScopeParams = { scopeId: ScopeId };
const SecretParams = { scopeId: ScopeId, secretId: SecretId };

// ---------------------------------------------------------------------------
// Response / payload schemas
// ---------------------------------------------------------------------------

const SecretRefResponse = Schema.Struct({
  id: SecretId,
  scopeId: ScopeId,
  name: Schema.String,
  provider: Schema.String,
  createdAt: Schema.Number,
});

const SecretStatusResponse = Schema.Struct({
  secretId: SecretId,
  status: Schema.Literals(["resolved", "missing"]),
});

const SetSecretPayload = Schema.Struct({
  id: SecretId,
  name: Schema.String,
  value: Schema.String,
  provider: Schema.optional(Schema.String),
});

// ---------------------------------------------------------------------------
// Error schemas with HTTP status annotations
// ---------------------------------------------------------------------------

const SecretNotFound = SecretNotFoundError.annotate({ httpApiStatus: 404 });
const SecretResolution = SecretResolutionError.annotate({ httpApiStatus: 500 });
const SecretOwnedByConnection = SecretOwnedByConnectionError.annotate({ httpApiStatus: 409 });
const SecretInUse = SecretInUseError.annotate({ httpApiStatus: 409 });

// ---------------------------------------------------------------------------
// Group
// ---------------------------------------------------------------------------

export const SecretsApi = HttpApiGroup.make("secrets")
  .add(
    HttpApiEndpoint.get("list", "/scopes/:scopeId/secrets", {
      params: ScopeParams,
      success: Schema.Array(SecretRefResponse),
      error: InternalError,
    }),
  )
  .add(
    HttpApiEndpoint.get("listAll", "/scopes/:scopeId/secrets/all", {
      params: ScopeParams,
      success: Schema.Array(SecretRefResponse),
      error: InternalError,
    }),
  )
  .add(
    HttpApiEndpoint.get("status", "/scopes/:scopeId/secrets/:secretId/status", {
      params: SecretParams,
      success: SecretStatusResponse,
      error: InternalError,
    }),
  )
  .add(
    HttpApiEndpoint.post("set", "/scopes/:scopeId/secrets", {
      params: ScopeParams,
      payload: SetSecretPayload,
      success: SecretRefResponse,
      error: [InternalError, SecretResolution],
    }),
  )
  .add(
    HttpApiEndpoint.delete("remove", "/scopes/:scopeId/secrets/:secretId", {
      params: SecretParams,
      success: Schema.Struct({ removed: Schema.Boolean }),
      error: [InternalError, SecretNotFound, SecretOwnedByConnection, SecretInUse],
    }),
  )
  .add(
    HttpApiEndpoint.get("usages", "/scopes/:scopeId/secrets/:secretId/usages", {
      params: SecretParams,
      success: Schema.Array(Usage),
      error: InternalError,
    }),
  );
