import { NextRequest, NextResponse } from "next/server";
import { GridColDef } from "@mui/x-data-grid-pro";
import { Database, db, getWorkerUtils } from "@link-stack/bridge-common";
import { getServiceTable } from "../config/config";

const entities = [
  "facebook",
  "whatsapp",
  "signal",
  "voice",
  "webhooks",
  "users",
] as const;

export type Entity = (typeof entities)[number];

export type SelectOption = {
  value: string;
  label: string;
};

export type FieldDescription = {
  name: string;
  label: string;
  kind?: "text" | "phone" | "select" | "multi" | "qrcode";
  getValue?: (token: string) => Promise<string>;
  getQRCode?: (token: string) => Promise<Record<string, string>>;
  refreshInterval?: number;
  getOptions?: (formState: any) => Promise<SelectOption[]>;
  autogenerated?: "token";
  hidden?: boolean;
  type?: string;
  lines?: number;
  copyable?: boolean;
  refreshable?: boolean;
  defaultValue?: string;
  required?: boolean;
  disabled?: boolean;
  size?: number;
  helperText?: string;
};

export type ServiceConfig = {
  entity: Entity;
  table: keyof Database;
  displayName: string;
  createFields: FieldDescription[];
  updateFields: FieldDescription[];
  displayFields: FieldDescription[];
  listColumns: GridColDef[];
};

export type ServiceParams = {
  params: {
    service: string;
    token?: string;
  };
};

export class Service {
  async getBot({
    params: { service, token },
  }: ServiceParams): Promise<NextResponse> {
    const table = getServiceTable(service);
    const row = await db
      .selectFrom(table)
      .selectAll()
      .where("token", "=", token ?? "NEVER_MATCH")
      .executeTakeFirstOrThrow();

    return NextResponse.json(row);
  }

  async registerBot({
    params: { service, token },
  }: ServiceParams): Promise<NextResponse> {
    return NextResponse.error() as any;
  }

  async sendMessage(
    req: NextRequest,
    { params: { service, token } }: ServiceParams,
  ): Promise<NextResponse> {
    const table = getServiceTable(service);
    const row = await db
      .selectFrom(table)
      .selectAll()
      .where("token", "=", token ?? "NEVER_MATCH")
      .executeTakeFirstOrThrow();
    const json = await req.json();
    const worker = await getWorkerUtils();
    await worker.addJob(`${service}/send-${service}-message`, {
      token,
      ...json,
    });

    const response = {
      response: "ok",
      result: {
        to: json.to,
        from: row?.phoneNumber ?? null,
        timestamp: new Date().toISOString(),
      },
    };

    console.log(response);
    return NextResponse.json(response);
  }

  async receiveMessage(
    req: NextRequest,
    { params: { service, token } }: ServiceParams,
  ): Promise<NextResponse> {
    const json = await req.json();
    const worker = await getWorkerUtils();
    await worker.addJob(`${service}/receive-${service}-message`, {
      token,
      ...json,
    });

    return NextResponse.json({ response: "ok" });
  }

  async handleWebhook(_req: NextRequest): Promise<NextResponse> {
    return NextResponse.error() as any;
  }
}
