import { Injectable, Logger } from "@nestjs/common";

export type EvolutionCreateResult = {
  instance?: {
    instanceName?: string;
    instanceId?: string;
    status?: string;
  };
  hash?: string;
  qrcode?: {
    base64?: string;
    code?: string;
    pairingCode?: string | null;
    count?: number;
  };
};

@Injectable()
export class EvolutionClient {
  private readonly logger = new Logger(EvolutionClient.name);

  private get baseUrl() {
    return (process.env.EVOLUTION_BASE_URL || "http://localhost:8080").replace(
      /\/$/,
      "",
    );
  }

  private get apiKey() {
    return process.env.EVOLUTION_API_KEY || "";
  }

  private async request<T>(
    method: string,
    path: string,
    body?: unknown,
  ): Promise<T> {
    const url = `${this.baseUrl}${path}`;
    const res = await fetch(url, {
      method,
      headers: {
        apikey: this.apiKey,
        "Content-Type": "application/json",
      },
      body: body === undefined ? undefined : JSON.stringify(body),
    });
    const text = await res.text();
    let data: unknown = null;
    try {
      data = text ? JSON.parse(text) : null;
    } catch {
      data = { raw: text };
    }
    if (!res.ok) {
      this.logger.warn(`Evolution ${method} ${path} → ${res.status}: ${text}`);
      throw new Error(
        `Evolution ${method} ${path} failed (${res.status}): ${text}`,
      );
    }
    return data as T;
  }

  createInstance(payload: {
    instanceName: string;
    qrcode?: boolean;
    webhook?: {
      enabled: boolean;
      url: string;
      events: string[];
    };
  }): Promise<EvolutionCreateResult> {
    return this.request<EvolutionCreateResult>(
      "POST",
      "/instance/create",
      payload,
    );
  }

  connect(instanceName: string): Promise<EvolutionCreateResult["qrcode"]> {
    return this.request("GET", `/instance/connect/${encodeURIComponent(instanceName)}`);
  }

  connectionState(instanceName: string): Promise<{
    instance?: { instanceName?: string; state?: string };
  }> {
    return this.request(
      "GET",
      `/instance/connectionState/${encodeURIComponent(instanceName)}`,
    );
  }

  logout(instanceName: string): Promise<unknown> {
    return this.request(
      "DELETE",
      `/instance/logout/${encodeURIComponent(instanceName)}`,
    );
  }

  delete(instanceName: string): Promise<unknown> {
    return this.request(
      "DELETE",
      `/instance/delete/${encodeURIComponent(instanceName)}`,
    );
  }
}
