/* eslint-disable camelcase,@typescript-eslint/explicit-module-boundary-types,@typescript-eslint/no-explicit-any */
import querystring from "querystring";
import Wreck from "@hapi/wreck";

export interface User {
  id: number;
  firstname?: string;
  lastname?: string;
  email?: string;
  phone?: string;
}
export interface Ticket {
  id: number;
  title?: string;
  group_id?: number;
  customer_id?: number;
}

export interface ZammadClient {
  ticket: {
    create: (data: any) => Promise<Ticket>;
  };
  user: {
    search: (data: any) => Promise<User[]>;
    create: (data: any) => Promise<User>;
  };
}

export type ZammadCredentials =
  | { username: string; password: string }
  | { token: string };

export interface ZammadClientOpts {
  headers?: Record<string, any>;
}

const formatAuth = (credentials: any) => {
  if (credentials.username) {
    return (
      "Basic " +
      Buffer.from(`${credentials.username}:${credentials.password}`).toString(
        "base64"
      )
    );
  }

  if (credentials.token) {
    return `Token ${credentials.token}`;
  }

  throw new Error("invalid zammad credentials type");
};

export const Zammad = (
  credentials: ZammadCredentials,
  host: string,
  opts?: ZammadClientOpts
): ZammadClient => {
  const extraHeaders = (opts && opts.headers) || {};

  const wreck = Wreck.defaults({
    baseUrl: `${host}/api/v1/`,
    headers: {
      authorization: formatAuth(credentials),
      ...extraHeaders,
    },
    json: true,
  });

  return {
    ticket: {
      create: async (payload) => {
        const { payload: result } = await wreck.post("tickets", { payload });
        return result as Ticket;
      },
    },
    user: {
      search: async (query) => {
        const qp = querystring.stringify({ query });
        const { payload: result } = await wreck.get(`users/search?${qp}`);
        return result as User[];
      },
      create: async (payload) => {
        const { payload: result } = await wreck.post("users", { payload });
        return result as User;
      },
    },
  };
};

export const getUser = async (zammad: ZammadClient, phoneNumber: string) => {
  const mungedNumber = phoneNumber.replace("+", "");
  const results = await zammad.user.search(`phone:${mungedNumber}`);
  if (results.length > 0) return results[0];
  return undefined;
};

export const getOrCreateUser = async (zammad: ZammadClient, phoneNumber: string) => {
  const customer = await getUser(zammad, phoneNumber);
  if (customer) return customer;

  return zammad.user.create({
    phone: phoneNumber,
    note: "User created by Grabadora from incoming voice call",
  });
};
