import { writeGeneratedFile } from "../../helpers/fs";
import { generateFileHeader } from "../types/fileHeader";

const FILE_NAME = "webhook.ts";

export function generateWebhookFetcher(outputDir: string): void {
  const content = `${generateFileHeader(FILE_NAME)}
import { AttioClient } from "./attioClient";
import { BaseFetcher } from "./base";
import {
  AttioWebhook,
  AttioWebhookEventType,
  CreateWebhookInput,
  WebhookEventData,
  WebhookQueryParams,
} from "../types";

export type AttioWebhookEventListener<T = any> = (data: T) => void | Promise<void>;
export type AttioWebhookEventPopulatedListener<P = any, D = any> = (params: { payload: P; data: D }) => void | Promise<void>;

export class AttioWebhookFetcher extends BaseFetcher {
  private readonly eventListeners = new Map<
    AttioWebhookEventType,
    AttioWebhookEventListener[]
  >();

  constructor(client: AttioClient) {
    super(client);
  }

  protected createBaseUrl(): string {
    return "/webhooks";
  }

  async getAll(query: WebhookQueryParams = {}): Promise<AttioWebhook[]> {
    return this.extractData<AttioWebhook[]>(
      this.client.doFetch(this.createBaseUrl(), {
        query,
      })
    );
  }

  async getById(id: string): Promise<AttioWebhook> {
    return this.extractData<AttioWebhook>(
      this.client.doFetch(\`\${this.createBaseUrl()}/\${id}\`)
    );
  }

  async create(data: CreateWebhookInput): Promise<AttioWebhook> {
    return this.extractData<AttioWebhook>(
      this.client.doFetch(this.createBaseUrl(), {
        method: "POST",
        body: data,
      })
    );
  }

  async update(id: string, data: Partial<CreateWebhookInput>): Promise<AttioWebhook> {
    return this.extractData<AttioWebhook>(
      this.client.doFetch(\`\${this.createBaseUrl()}/\${id}\`, {
        method: "PUT",
        body: data,
      })
    );
  }

  async delete(id: string): Promise<void> {
    await this.client.doFetch(\`\${this.createBaseUrl()}/\${id}\`, {
      method: "DELETE",
    });
  }

  on(
    event: AttioWebhookEventType,
    eventHandler: AttioWebhookEventListener
  ): void {
    if (!this.eventListeners.has(event)) {
      this.eventListeners.set(event, []);
    }
    this.eventListeners.get(event)!.push(eventHandler);
  }

  removeAllListeners(
    event: AttioWebhookEventType,
  ): void {
    if (this.eventListeners.has(event)) {
      this.eventListeners.set(event, []);
    }
  }

  async handleWebhookEvent(
    data: WebhookEventData,
  ): Promise<void> {
    if (!this.eventListeners.has(data.event_type)) {
      return;
    }

    const listeners = this.eventListeners.get(data.event_type)!;
    await Promise.allSettled(
      listeners.map((listener) => listener(data))
    );
  }
}
`;

  writeGeneratedFile(outputDir, FILE_NAME, content);
}
