"use client";

/**
 * Typed client-side fetch service.
 *
 * All client components MUST use these helpers instead of raw `fetch()`
 * so every call/response follows the same `{ ok, data?, error? }` shape.
 */

export interface ApiResponse<T = unknown> {
  ok: boolean;
  data?: T;
  total?: number;
  error?: any;
}

async function request<T>(
  url: string,
  options?: RequestInit
): Promise<ApiResponse<T>> {
  try {
    const res = await fetch(url, options);
    const json = (await res.json()) as ApiResponse<T>;
    return json;
  } catch (err) {
    return { ok: false, error: err instanceof Error ? err.message : String(err) };
  }
}

export const api = {
  get<T>(url: string): Promise<ApiResponse<T>> {
    return request<T>(url);
  },

  post<T>(url: string, body: unknown): Promise<ApiResponse<T>> {
    return request<T>(url, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(body),
    });
  },

  put<T>(url: string, body: unknown): Promise<ApiResponse<T>> {
    return request<T>(url, {
      method: "PUT",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(body),
    });
  },

  patch<T>(url: string, body: unknown): Promise<ApiResponse<T>> {
    return request<T>(url, {
      method: "PATCH",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(body),
    });
  },

  delete<T>(url: string, body?: unknown): Promise<ApiResponse<T>> {
    const options: RequestInit = { method: "DELETE" };
    if (body) {
      options.headers = { "Content-Type": "application/json" };
      options.body = JSON.stringify(body);
    }
    return request<T>(url, options);
  },

  async download(url: string, body: unknown): Promise<{ ok: boolean; blob?: Blob; filename?: string; error?: any }> {
    try {
      const res = await fetch(url, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(body),
      });

      console.log(`Download response status: ${res.status}, Content-Type: ${res.headers.get('Content-Type')}`);

      if (!res.ok) {
        try {
          const json = await res.json();
          console.error('Download error response:', json);
          return { ok: false, error: json.error || "Download failed" };
        } catch (parseErr) {
          // If response is not JSON, try to get text
          const text = await res.text();
          console.error('Download error (non-JSON):', text);
          return { ok: false, error: text || `HTTP ${res.status}: Download failed` };
        }
      }

      const blob = await res.blob();
      console.log(`Downloaded blob size: ${blob.size} bytes`);
      
      let filename = "download";
      const contentDisposition = res.headers.get("Content-Disposition");
      if (contentDisposition) {
        const match = contentDisposition.match(/filename="([^"]+)"/);
        if (match) filename = match[1];
      }

      return { ok: true, blob, filename };
    } catch (err) {
      console.error('Download error:', err);
      return { ok: false, error: err instanceof Error ? err.message : String(err) };
    }
  },
};
