import type { CreateBucketCommandInput } from "@aws-sdk/client-s3";

export function optionalEnv(name: string, env: NodeJS.ProcessEnv = process.env): string | undefined {
  const value = env[name]?.trim();
  return value ? value : undefined;
}

const DEFAULT_CORS_ORIGINS = [
  "http://localhost:3000",
  "http://127.0.0.1:3000",
  "http://localhost:3001",
  "http://127.0.0.1:3001",
  "https://api-new.windshieldhub.com",
  "https://api-new.windshieldhub.com/app",
].join(",");

export function s3CorsOrigins(env: NodeJS.ProcessEnv = process.env): string[] {
  return (optionalEnv("S3_CORS_ORIGINS", env) ?? DEFAULT_CORS_ORIGINS)
    .split(",")
    .map((origin) => origin.trim())
    .filter(Boolean);
}

/** MinIO/local S3 clones need a custom endpoint; Amazon S3 must not have one. */
export function s3CustomEndpoint(env: NodeJS.ProcessEnv = process.env): string | undefined {
  return optionalEnv("S3_ENDPOINT", env);
}

export function createBucketInput(
  bucket: string,
  region: string,
  customEndpoint?: string,
): CreateBucketCommandInput {
  if (customEndpoint || region === "us-east-1") return { Bucket: bucket };
  return {
    Bucket: bucket,
    CreateBucketConfiguration: {
      LocationConstraint: region as NonNullable<CreateBucketCommandInput["CreateBucketConfiguration"]>["LocationConstraint"],
    },
  };
}

function s3Meta(error: unknown): { name?: string; status?: number } {
  const err = error as { name?: string; Code?: string; $metadata?: { httpStatusCode?: number } };
  return { name: err?.name ?? err?.Code, status: err?.$metadata?.httpStatusCode };
}

export function describeS3Error(error: unknown): string {
  const err = error as { name?: string; message?: string; $metadata?: { httpStatusCode?: number } };
  const status = err?.$metadata?.httpStatusCode;
  return [err?.name, status ? `HTTP ${status}` : null, err?.message].filter(Boolean).join(": ");
}

/** HeadBucket on a missing bucket. AWS may also return 403 to hide existence. */
export function isMissingBucket(error: unknown): boolean {
  const { name, status } = s3Meta(error);
  return name === "NotFound" || name === "NoSuchBucket" || status === 404;
}

export function isForbidden(error: unknown): boolean {
  const { name, status } = s3Meta(error);
  return status === 403 || name === "AccessDenied" || name === "Forbidden";
}

/** HeadObject on a key that is not there — the bucket itself is reachable. */
export function isMissingObject(error: unknown): boolean {
  const { name, status } = s3Meta(error);
  return name === "NotFound" || name === "NoSuchKey" || status === 404;
}
