// ============================================================================
// CloseBot API HTTP Client
// ============================================================================

const BASE_URL = "https://api.closebot.com";

export class CloseBotClient {
  private apiKey: string;
  private baseUrl: string;

  constructor(apiKey?: string, baseUrl?: string) {
    this.apiKey = apiKey || process.env.CLOSEBOT_API_KEY || "";
    this.baseUrl = baseUrl || process.env.CLOSEBOT_BASE_URL || BASE_URL;

    if (!this.apiKey) {
      throw new Error(
        "CloseBot API key is required. Set CLOSEBOT_API_KEY environment variable."
      );
    }
  }

  private buildUrl(path: string, query?: Record<string, unknown>): string {
    const url = new URL(path, this.baseUrl);
    if (query) {
      for (const [key, value] of Object.entries(query)) {
        if (value !== undefined && value !== null && value !== "") {
          url.searchParams.set(key, String(value));
        }
      }
    }
    return url.toString();
  }

  private get headers(): Record<string, string> {
    return {
      "X-CB-KEY": this.apiKey,
      "Content-Type": "application/json",
      Accept: "application/json",
    };
  }

  async get<T = unknown>(
    path: string,
    query?: Record<string, unknown>
  ): Promise<T> {
    const url = this.buildUrl(path, query);
    const response = await fetch(url, {
      method: "GET",
      headers: this.headers,
    });
    return this.handleResponse<T>(response);
  }

  async post<T = unknown>(
    path: string,
    body?: unknown,
    query?: Record<string, unknown>
  ): Promise<T> {
    const url = this.buildUrl(path, query);
    const options: RequestInit = {
      method: "POST",
      headers: this.headers,
    };
    if (body !== undefined) {
      options.body = JSON.stringify(body);
    }
    const response = await fetch(url, options);
    return this.handleResponse<T>(response);
  }

  async put<T = unknown>(
    path: string,
    body?: unknown,
    query?: Record<string, unknown>
  ): Promise<T> {
    const url = this.buildUrl(path, query);
    const options: RequestInit = {
      method: "PUT",
      headers: this.headers,
    };
    if (body !== undefined) {
      options.body = JSON.stringify(body);
    }
    const response = await fetch(url, options);
    return this.handleResponse<T>(response);
  }

  async delete<T = unknown>(
    path: string,
    query?: Record<string, unknown>
  ): Promise<T> {
    const url = this.buildUrl(path, query);
    const response = await fetch(url, {
      method: "DELETE",
      headers: this.headers,
    });
    return this.handleResponse<T>(response);
  }

  async postFormData<T = unknown>(
    path: string,
    formData: FormData,
    query?: Record<string, unknown>
  ): Promise<T> {
    const url = this.buildUrl(path, query);
    const headers: Record<string, string> = {
      "X-CB-KEY": this.apiKey,
      Accept: "application/json",
    };
    const response = await fetch(url, {
      method: "POST",
      headers,
      body: formData,
    });
    return this.handleResponse<T>(response);
  }

  async putFormData<T = unknown>(
    path: string,
    formData: FormData,
    query?: Record<string, unknown>
  ): Promise<T> {
    const url = this.buildUrl(path, query);
    const headers: Record<string, string> = {
      "X-CB-KEY": this.apiKey,
      Accept: "application/json",
    };
    const response = await fetch(url, {
      method: "PUT",
      headers,
      body: formData,
    });
    return this.handleResponse<T>(response);
  }

  private async handleResponse<T>(response: Response): Promise<T> {
    if (!response.ok) {
      let errorBody: string;
      try {
        errorBody = await response.text();
      } catch {
        errorBody = "Unable to read error body";
      }
      throw new ApiError(
        `CloseBot API error ${response.status}: ${response.statusText}`,
        response.status,
        errorBody
      );
    }

    const contentType = response.headers.get("content-type");
    if (!contentType || response.status === 204) {
      return {} as T;
    }

    if (contentType.includes("application/json") || contentType.includes("text/json")) {
      return (await response.json()) as T;
    }

    const text = await response.text();
    try {
      return JSON.parse(text) as T;
    } catch {
      return text as unknown as T;
    }
  }
}

export class ApiError extends Error {
  public statusCode: number;
  public responseBody: string;

  constructor(message: string, statusCode: number, responseBody: string) {
    super(message);
    this.name = "ApiError";
    this.statusCode = statusCode;
    this.responseBody = responseBody;
  }
}

/** Format API result as MCP text content */
export function ok(data: unknown): {
  content: Array<{ type: "text"; text: string }>;
} {
  return {
    content: [
      {
        type: "text" as const,
        text: typeof data === "string" ? data : JSON.stringify(data, null, 2),
      },
    ],
  };
}

/** Format error as MCP error content */
export function err(error: unknown): {
  content: Array<{ type: "text"; text: string }>;
  isError: boolean;
} {
  const message =
    error instanceof ApiError
      ? `API Error ${error.statusCode}: ${error.message}\n${error.responseBody}`
      : error instanceof Error
        ? error.message
        : String(error);
  return {
    content: [{ type: "text" as const, text: message }],
    isError: true,
  };
}
