// Lightweight axios shim (~2KB) for CF Workers — replaces full axios (115KB).
// Only implements the API surface actually used by payment-kit:
//   axios.get(url, config)
//   axios.create(defaults) → instance with .get()
//   AxiosError with .response

export class AxiosError extends Error {
  response?: { status: number; data: any; headers: Record<string, string> };
  config?: any;
  code?: string;
  isAxiosError = true;

  constructor(message: string, code?: string, config?: any, response?: AxiosError['response']) {
    super(message);
    this.name = 'AxiosError';
    this.code = code;
    this.config = config;
    this.response = response;
  }
}

interface AxiosConfig {
  params?: Record<string, any>;
  timeout?: number;
  headers?: Record<string, string>;
  baseURL?: string;
}

interface AxiosResponse<T = any> {
  data: T;
  status: number;
  statusText: string;
  headers: Record<string, string>;
}

async function request<T = any>(url: string, config: AxiosConfig = {}): Promise<AxiosResponse<T>> {
  const { params, timeout, headers = {}, baseURL } = config;

  let fullUrl = baseURL ? `${baseURL.replace(/\/$/, '')}/${url.replace(/^\//, '')}` : url;

  if (params) {
    const qs = new URLSearchParams();
    for (const [k, v] of Object.entries(params)) {
      if (v !== undefined && v !== null) qs.append(k, String(v));
    }
    const sep = fullUrl.includes('?') ? '&' : '?';
    fullUrl = `${fullUrl}${sep}${qs.toString()}`;
  }

  const controller = new AbortController();
  const timeoutMs = timeout || 30000;
  const timer = setTimeout(() => controller.abort(), timeoutMs);

  let res: Response;
  try {
    res = await fetch(fullUrl, { headers, signal: controller.signal });
  } catch (err: any) {
    clearTimeout(timer);
    const code = err?.name === 'AbortError' ? 'ECONNABORTED' : 'ERR_NETWORK';
    throw new AxiosError(err?.message || 'Network Error', code, config);
  } finally {
    clearTimeout(timer);
  }

  const responseHeaders: Record<string, string> = {};
  res.headers.forEach((v, k) => { responseHeaders[k] = v; });

  const ct = res.headers.get('content-type') || '';
  const data = ct.includes('application/json') ? await res.json() : await res.text();

  const response: AxiosResponse<T> = {
    data: data as T,
    status: res.status,
    statusText: res.statusText,
    headers: responseHeaders,
  };

  if (!res.ok) {
    throw new AxiosError(
      `Request failed with status code ${res.status}`,
      'ERR_BAD_RESPONSE',
      config,
      { status: res.status, data, headers: responseHeaders },
    );
  }

  return response;
}

function createInstance(defaults: AxiosConfig = {}) {
  const instance = {
    defaults,
    get<T = any>(url: string, config: AxiosConfig = {}): Promise<AxiosResponse<T>> {
      return request<T>(url, { ...defaults, ...config, headers: { ...defaults.headers, ...config.headers } });
    },
    post<T = any>(url: string, _body?: any, config: AxiosConfig = {}): Promise<AxiosResponse<T>> {
      return request<T>(url, { ...defaults, ...config, headers: { ...defaults.headers, ...config.headers } });
    },
    request<T = any>(config: AxiosConfig & { url: string }): Promise<AxiosResponse<T>> {
      const { url, ...rest } = config;
      return request<T>(url, { ...defaults, ...rest, headers: { ...defaults.headers, ...rest.headers } });
    },
  };
  return instance;
}

const axios = {
  get: <T = any>(url: string, config?: AxiosConfig) => request<T>(url, config),
  post: <T = any>(url: string, _body?: any, config?: AxiosConfig) => request<T>(url, config),
  create: (defaults?: AxiosConfig) => createInstance(defaults),
  isAxiosError: (err: any): err is AxiosError => err?.isAxiosError === true,
  AxiosError,
};

export default axios;
export { axios, AxiosError as default_AxiosError };
export type { AxiosConfig, AxiosResponse };
