import {
  Address,
  Center,
  Civility,
  DateTime,
  SetAddress,
  SetCivility,
  User,
} from "ChillMainAssets/types";

export type ThirdPartyKind = "contact" | "child" | "company";

export interface BaseThirdParty {
  type: "thirdparty";
  kind: "" | ThirdPartyKind;
  text: string;
  acronym: string | null;
  active: boolean;
  address: Address | null;
  contactDataAnonymous: boolean;
  createdAt: DateTime;
  createdBy: User | null;
  email: string | null;
  firstname: string | null;
  id: number;
  nameCompany: string | null;
  telephone: string | null;
  telephone2: string | null;
  updatedAt: DateTime | null;
  updatedBy: User | null;
}

function isBaseThirdParty(t: unknown): t is BaseThirdParty {
  if (typeof t !== "object" || t === null) return false;
  const o = t as Partial<BaseThirdParty>;
  return (
    (o as any).type === "thirdparty" &&
    typeof o.id === "number" &&
    typeof o.text === "string" &&
    (o.kind === "" ||
      o.kind === "contact" ||
      o.kind === "child" ||
      o.kind === "company") &&
    typeof o.active === "boolean"
  );
}

export interface ThirdpartyCompany extends BaseThirdParty {
  kind: "company";
  text: string;
  acronym: string | null;
  children: Thirdparty[];
  category: ThirdpartyCategory[];
  thirdPartyTypes: ThirdpartyType[] | null;
  address: Address | null;
}

// Type guard to distinguish a ThirdpartyCompany
export function isThirdpartyCompany(t: BaseThirdParty): t is ThirdpartyCompany {
  return t.type === "thirdparty" && t.kind === "company";
}

export interface ThirdpartyChild extends BaseThirdParty {
  kind: "child";
  civility: Civility | null;
  contactDataAnonymous: boolean;
  parent: ThirdpartyCompany;
  profession: string;
  firstname: string;
  /**
   * the lastname for "Contact" and "Child", the name
   */
  name: string;
  comment: string | null;
}

// Type guard to distinguish a ThirdpartyChild
export function isThirdpartyChild(t: BaseThirdParty): t is ThirdpartyChild {
  return t.type === "thirdparty" && t.kind === "child";
}

export interface ThirdpartyContact extends BaseThirdParty {
  kind: "contact";
  civility: Civility | null;
  category: ThirdpartyCategory[];
  thirdPartyTypes: ThirdpartyType[] | null;
  profession: string;
  firstname: string;
  /**
   * the lastname for "Contact" and "Child", the name
   */
  name: string;
  address: Address | null;
}

// Type guard to distinguish a ThirdpartyContact
export function isThirdpartyContact(t: BaseThirdParty): t is ThirdpartyContact {
  return t.type === "thirdparty" && t.kind === "contact";
}

export type Thirdparty =
  | ThirdpartyCompany
  | ThirdpartyContact
  | ThirdpartyChild;

export function isThirdparty(t: unknown): t is Thirdparty {
  if (!isBaseThirdParty(t)) {
    return false;
  }

  return (
    isThirdpartyCompany(t) || isThirdpartyContact(t) || isThirdpartyChild(t)
  );
}

interface ThirdpartyType {
  key: string;
  value: string;
}

export interface ThirdpartyCategory {
  id: number;
  active: boolean;
  name: {
    fr: string;
  };
}

/**
 * Associate an existing ThirdParty during write operation.
 */
export interface SetThirdParty {
  readonly type: "thirdparty";
  id: number;
}

export interface ThirdPartyWrite {
  readonly type: "thirdparty";
  kind: ThirdPartyKind;
  civility: SetCivility | null;
  profession: string;
  firstname: string;
  /**
   * the lastname
   */
  name: string;
  email: string;
  telephone: string;
  telephone2: string;
  address: null | SetAddress;
  comment: string;
  parent: SetThirdParty | null;
}
