import { createClient } from "@/lib/supabase/client";
import type { ApiError } from "@/lib/types";

class ApiClient {
  private baseUrl = "/api";

  /** Strip leading /api/ if accidentally included — baseUrl already provides it */
  private normalizePath(path: string): string {
    if (path.startsWith("/api/")) {
      return path.slice(4); // "/api/foo" -> "/foo"
    }
    return path;
  }

  private async getHeaders(): Promise<HeadersInit> {
    const supabase = createClient();
    const {
      data: { session },
    } = await supabase.auth.getSession();

    const headers: HeadersInit = {
      "Content-Type": "application/json",
    };

    if (session?.access_token) {
      headers["Authorization"] = `Bearer ${session.access_token}`;
    }

    const tenantId = typeof window !== "undefined"
      ? localStorage.getItem("kanzlai_tenant_id")
      : null;
    if (tenantId) {
      headers["X-Tenant-ID"] = tenantId;
    }

    return headers;
  }

  private async request<T>(
    rawPath: string,
    options: RequestInit = {},
  ): Promise<T> {
    const path = this.normalizePath(rawPath);
    const headers = await this.getHeaders();
    const res = await fetch(`${this.baseUrl}${path}`, {
      ...options,
      headers: { ...headers, ...options.headers },
    });

    if (!res.ok) {
      const body = await res.json().catch(() => ({}));
      const err: ApiError = {
        error: body.error || res.statusText,
        status: res.status,
      };
      throw err;
    }

    if (res.status === 204) return undefined as T;
    return res.json();
  }

  get<T>(path: string) {
    return this.request<T>(path, { method: "GET" });
  }

  post<T>(path: string, body?: unknown) {
    return this.request<T>(path, {
      method: "POST",
      body: body ? JSON.stringify(body) : undefined,
    });
  }

  put<T>(path: string, body?: unknown) {
    return this.request<T>(path, {
      method: "PUT",
      body: body ? JSON.stringify(body) : undefined,
    });
  }

  patch<T>(path: string, body?: unknown) {
    return this.request<T>(path, {
      method: "PATCH",
      body: body ? JSON.stringify(body) : undefined,
    });
  }

  delete<T>(path: string) {
    return this.request<T>(path, { method: "DELETE" });
  }

  async postFormData<T>(rawPath: string, formData: FormData): Promise<T> {
    const path = this.normalizePath(rawPath);
    const supabase = createClient();
    const {
      data: { session },
    } = await supabase.auth.getSession();

    const headers: HeadersInit = {};
    if (session?.access_token) {
      headers["Authorization"] = `Bearer ${session.access_token}`;
    }
    const tenantId = typeof window !== "undefined"
      ? localStorage.getItem("kanzlai_tenant_id")
      : null;
    if (tenantId) {
      headers["X-Tenant-ID"] = tenantId;
    }

    const res = await fetch(`${this.baseUrl}${path}`, {
      method: "POST",
      headers,
      body: formData,
    });

    if (!res.ok) {
      const body = await res.json().catch(() => ({}));
      const err: ApiError = {
        error: body.error || res.statusText,
        status: res.status,
      };
      throw err;
    }

    return res.json();
  }
}

export const api = new ApiClient();
