<template>
  <div>
    <div v-if="resolvedParent">
      <div class="parent-info">
        <i class="fa fa-li fa-hand-o-right" />
        <b class="me-2">{{ trans(THIRDPARTY_MESSAGES_CHILD_OF) }}</b>
        <span class="chill-entity badge-thirdparty">{{
          resolvedParent.text
        }}</span>
      </div>
    </div>
    <div class="form-floating mb-3" v-else-if="props.action === 'create'">
      <div class="form-check">
        <input
          class="form-check-input mt-0"
          type="radio"
          v-model="kind"
          value="company"
          id="tpartyKindInstitution"
        />
        <label for="tpartyKindInstitution" class="required">
          <badge-entity
            :entity="{ type: 'thirdparty', kind: 'company' }"
            :options="{ displayLong: true }"
          />
        </label>
      </div>
      <div class="form-check">
        <input
          class="form-check-input mt-0"
          type="radio"
          v-model="kind"
          value="contact"
          id="tpartyKindContact"
        />
        <label for="tpartyKindContact" class="required">
          <badge-entity
            :entity="{ type: 'thirdparty', kind: 'contact' }"
            :options="{ displayLong: true }"
          />
        </label>
      </div>
    </div>
    <div v-else-if="resolvedParent">
      <p>Contact de&nbsp;:</p>
      <third-party-render-box
        :thirdparty="resolvedParent"
        :options="{
          addInfo: true,
          addEntity: false,
          addId: false,
          addLink: false,
          hLevel: 4,
          isMultiline: false,
        }"
      />
    </div>

    <div v-if="thirdParty.kind === 'child' || thirdParty.kind === 'contact'">
      <div class="child-info">
        <div class="input-section">
          <div class="mb-3">
            <div class="input-group">
              <div class="form-floating">
                <select
                  class="form-select form-select-lg"
                  name="civility"
                  id="civility"
                  v-model="civility"
                >
                  <option selected disabled :value="null">
                    {{ trans(THIRDPARTY_MESSAGES_THIRDPARTY_CIVILITY) }}
                  </option>
                  <option
                    v-for="civility in civilities"
                    :key="civility.id"
                    :value="civility.id"
                  >
                    {{ localizeString(civility.name) }}
                  </option>
                </select>
                <label for="civility">{{
                  trans(THIRDPARTY_MESSAGES_THIRDPARTY_CIVILITY)
                }}</label>
              </div>
            </div>
          </div>
        </div>
        <div class="input-section">
          <div class="mb-3">
            <div class="form-floating">
              <input
                class="form-control form-control-lg"
                name="profession"
                v-model="thirdParty.profession"
                :placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_PROFESSION)"
                :aria-label="trans(THIRDPARTY_MESSAGES_THIRDPARTY_PROFESSION)"
                aria-describedby="profession"
              />
              <label for="profession">{{
                trans(THIRDPARTY_MESSAGES_THIRDPARTY_PROFESSION)
              }}</label>
            </div>
          </div>
        </div>
      </div>
      <div class="child-info">
        <div class="input-section">
          <div class="mb-3">
            <div class="input-group">
              <div class="form-floating">
                <input
                  class="form-control form-control-lg"
                  id="firstname"
                  v-model="thirdParty.firstname"
                  :placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_FIRSTNAME)"
                />
                <label for="firstname">{{
                  trans(THIRDPARTY_MESSAGES_THIRDPARTY_FIRSTNAME)
                }}</label>
              </div>
            </div>
            <div v-if="queryItems">
              <ul class="list-suggest add-items inline">
                <li
                  v-for="(qi, i) in queryItems"
                  :key="i"
                  @click="addQueryItem('firstName', qi)"
                >
                  <span class="person-text">{{ qi }}</span>
                </li>
              </ul>
            </div>
          </div>
        </div>
        <div class="input-section">
          <div class="mb3">
            <div class="input-group has-validation">
              <div class="form-floating">
                <input
                  class="form-control form-control-lg"
                  :class="{ 'is-invalid': violations.hasViolation('name') }"
                  id="name"
                  v-model="thirdParty.name"
                  :placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_LASTNAME)"
                />
                <label for="name">{{
                  trans(THIRDPARTY_MESSAGES_THIRDPARTY_LASTNAME)
                }}</label>
              </div>
            </div>
            <div
              v-for="err in violations.violationTitles('name')"
              class="invalid-feedback was-validated-force"
            >
              {{ err }}
            </div>
            <div v-if="queryItems">
              <ul class="list-suggest add-items inline">
                <li
                  v-for="(qi, i) in queryItems"
                  :key="i"
                  @click="addQueryItem('name', qi)"
                >
                  <span class="person-text">{{ qi }}</span>
                </li>
              </ul>
            </div>
          </div>
        </div>
      </div>
    </div>

    <div v-if="thirdParty.kind === 'company'">
      <div class="mb-3">
        <div class="input-group">
          <div class="form-floating">
            <input
              class="form-control form-control-lg"
              :class="{ 'is-invalid': violations.hasViolation('name') }"
              id="name"
              v-model="thirdParty.name"
              :placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_NAME)"
            />
            <label for="name">{{
              trans(THIRDPARTY_MESSAGES_THIRDPARTY_NAME)
            }}</label>
          </div>
        </div>

        <div
          v-for="err in violations.violationTitles('name')"
          class="invalid-feedback was-validated-force"
        >
          {{ err }}
        </div>

        <div v-if="query">
          <ul class="list-suggest add-items inline">
            <li @click="addQuery(query)">
              <span class="person-text">{{ query }}</span>
            </li>
          </ul>
        </div>
      </div>
    </div>

    <template v-if="thirdParty.kind !== 'child'">
      <AddAddress
        key="thirdparty"
        :context="context"
        :options="addAddress.options"
        :address-changed-callback="submitAddress"
        ref="addAddressRef"
      />
    </template>

    <div class="mb-3">
      <div class="input-group has-validation">
        <span id="email" class="input-group-text">
          <i class="fa fa-fw fa-at" />
        </span>
        <div class="form-floating">
          <input
            class="form-control form-control-lg"
            :class="{ 'is-invalid': violations.hasViolation('email') }"
            name="email"
            v-model="thirdParty.email"
            :placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_EMAIL)"
            :aria-label="trans(THIRDPARTY_MESSAGES_THIRDPARTY_EMAIL)"
            aria-describedby="email"
          />
          <label for="email">{{
            trans(THIRDPARTY_MESSAGES_THIRDPARTY_EMAIL)
          }}</label>
        </div>
      </div>
      <div
        v-for="err in violations.violationTitles('email')"
        class="invalid-feedback was-validated-force"
      >
        {{ err }}
      </div>
    </div>

    <div class="mb-3">
      <div class="input-group has-validation">
        <span class="input-group-text" id="phonenumber">
          <i class="fa fa-fw fa-phone" />
        </span>
        <div class="form-floating">
          <input
            class="form-control form-control-lg"
            :class="{ 'is-invalid': violations.hasViolation('telephone') }"
            name="phonenumber"
            v-model="thirdParty.telephone"
            :placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER)"
            :aria-label="trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER)"
            aria-describedby="phonenumber"
          />
          <label for="phonenumber">{{
            trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER)
          }}</label>
        </div>
      </div>
      <div
        v-for="err in violations.violationTitles('telephone')"
        class="invalid-feedback was-validated-force"
      >
        {{ err }}
      </div>
    </div>

    <div class="mb-3">
      <div class="input-group has-validation">
        <span class="input-group-text" id="phonenumber2"
          ><i class="fa fa-fw fa-phone"
        /></span>
        <div class="form-floating">
          <input
            class="form-control form-control-lg"
            :class="{ 'is-invalid': violations.hasViolation('telephone2') }"
            name="phonenumber2"
            v-model="thirdParty.telephone2"
            :placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER2)"
            :aria-label="trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER2)"
            aria-describedby="phonenumber2"
          />
          <label for="phonenumber2">{{
            trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER2)
          }}</label>
        </div>
      </div>
      <div
        v-for="err in violations.violationTitles('telephone2')"
        class="invalid-feedback was-validated-force"
      >
        {{ err }}
      </div>
    </div>

    <div v-if="props.action !== 'addContact'">
      <div class="input-group mb-3">
        <span class="input-group-text" id="comment"
          ><i class="fa fa-fw fa-pencil"
        /></span>
        <textarea
          class="form-control form-control-lg"
          :placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_COMMENT)"
          v-model="thirdParty.comment"
        />
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, onMounted, getCurrentInstance } from "vue";
import ThirdPartyRenderBox from "../Entity/ThirdPartyRenderBox.vue";
import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress.vue";
import {
  createThirdParty,
  getThirdparty,
  patchThirdparty,
  thirdpartyToWriteThirdParty,
  WriteThirdPartyViolationMap,
} from "../../_api/OnTheFly";
import BadgeEntity from "ChillMainAssets/vuejs/_components/BadgeEntity.vue";
import { localizeString as _localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
import {
  trans,
  THIRDPARTY_MESSAGES_THIRDPARTY_FIRSTNAME,
  THIRDPARTY_MESSAGES_THIRDPARTY_LASTNAME,
  THIRDPARTY_MESSAGES_THIRDPARTY_NAME,
  THIRDPARTY_MESSAGES_THIRDPARTY_EMAIL,
  THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER,
  THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER2,
  THIRDPARTY_MESSAGES_THIRDPARTY_COMMENT,
  THIRDPARTY_MESSAGES_THIRDPARTY_PROFESSION,
  THIRDPARTY_MESSAGES_THIRDPARTY_CIVILITY,
  THIRDPARTY_MESSAGES_CHILD_OF,
  PERSON_EDIT_ERROR_WHILE_SAVING,
} from "translator";
import {
  createPerson,
  getCivilities,
  WritePersonViolationMap,
} from "ChillPersonAssets/vuejs/_api/OnTheFly";
import {
  isThirdpartyChild,
  isThirdpartyCompany,
  Thirdparty,
  ThirdpartyCompany,
  ThirdPartyKind,
  ThirdPartyWrite,
} from "../../../types";
import { Civility, SetCivility } from "ChillMainAssets/types";
import { isValidationException } from "ChillMainAssets/lib/api/apiMethods";
import { useViolationList } from "ChillMainAssets/vuejs/_composables/violationList";
import { useToast } from "vue-toast-notification";

interface ThirdPartyEditWriteProps {
  id?: number;
  type?: "thirdparty";
  action: "edit" | "create";
  query?: string;
  parent?: null;
}

interface ThirdPartyAddContactProps {
  id?: null;
  type?: "thirdparty";
  action: "addContact";
  query?: "";
  parent: ThirdpartyCompany;
}

type ThirdPartyEditProps = ThirdPartyAddContactProps | ThirdPartyEditWriteProps;

const props = withDefaults(defineProps<ThirdPartyEditProps>(), {
  type: "thirdparty",
  query: "",
  parent: null,
});

const emit =
  defineEmits<
    (e: "onThirdPartyCreated", payload: { thirdParty: Thirdparty }) => void
  >();

defineExpose({ postThirdParty });

const toast = useToast();

const thirdParty = ref<ThirdPartyWrite>({
  type: "thirdparty",
  kind: "company",
  address: null,
  civility: null,
  email: "",
  firstname: "",
  name: "",
  profession: "",
  telephone: "",
  telephone2: "",
  comment: "",
  parent: null,
});

const originalThirdParty = ref<Thirdparty | null>(null);

const civility = computed<number | null>({
  get: () => {
    if (thirdParty.value.civility !== null) {
      return thirdParty.value.civility.id;
    }

    return null;
  },
  set: (value: number | null) => {
    thirdParty.value.civility =
      value !== null ? { id: value, type: "chill_main_civility" } : null;
  },
});

const civilities = ref<Civility[]>([]);

const addAddress = reactive({
  options: {
    openPanesInModal: true,
    onlyButton: false,
    button: { size: "btn-sm" },
    title: { create: "add_an_address_title", edit: "edit_address" },
  },
});
const addAddressRef = ref<any>(null);

/**
 * We need a specific computed for the kind
 */
const kind = computed<ThirdPartyKind>({
  get() {
    return thirdParty.value.kind;
  },
  set(v) {
    thirdParty.value.kind = v;
  },
});

const context = computed(() => {
  const ctx: any = {
    target: { name: props.type, id: props.id },
    edit: false,
    addressId: null as number | null,
    defaults: (window as any).addaddress,
  };
  if (thirdParty.value.address) {
    ctx.addressId = thirdParty.value.address.id;
    ctx.edit = true;
  }
  return ctx;
});

const resolvedParent = computed<null | ThirdpartyCompany>(() => {
  if (
    null !== originalThirdParty.value &&
    isThirdpartyChild(originalThirdParty.value)
  ) {
    return originalThirdParty.value.parent;
  }

  return props.parent ?? null;
});

/**
 * Find the query items to display for suggestion
 */
const queryItems = computed(() => {
  const words: null | string[] = props.query ? props.query.split(" ") : null;

  if (null === words) {
    return null;
  }

  const firstNameWords = (thirdParty.value.firstname || "")
    .trim()
    .toLowerCase()
    .split(" ");
  const lastNameWords = (thirdParty.value.name || "")
    .trim()
    .toLowerCase()
    .split(" ");

  return words
    .filter((word) => !firstNameWords.includes(word.toLowerCase()))
    .filter((word) => !lastNameWords.includes(word.toLowerCase()));
});

function localizeString(str: any) {
  return _localizeString(str);
}

onMounted(() => {
  getCivilities().then((cv) => {
    civilities.value = cv;
  });
  if (props.action === "edit") {
    loadData();
  } else if (props.action === "addContact") {
    thirdParty.value.kind = "child";
    thirdParty.value.address = null;
    thirdParty.value.parent = { id: props.parent.id, type: "thirdparty" };
  }
});

async function loadData(): Promise<void> {
  if (!props.id) return Promise.resolve();
  const t = await getThirdparty(props.id);
  originalThirdParty.value = t;
  thirdParty.value = thirdpartyToWriteThirdParty(t);
}

function submitAddress(payload: { addressId: number }) {
  console.log(payload);
  thirdParty.value.address = { id: payload.addressId };
}

function addQueryItem(field: "name" | "firstName", queryItem: string) {
  switch (field) {
    case "name":
      if (thirdParty.value.name) {
        thirdParty.value.name += ` ${queryItem}`;
      } else {
        thirdParty.value.name = queryItem;
      }
      break;
    case "firstName":
      thirdParty.value.firstname = queryItem;
      break;
  }
}

function addQuery(query: string) {
  thirdParty.value.name = query;
}

const violations = useViolationList<WriteThirdPartyViolationMap>();

async function postThirdParty(): Promise<Thirdparty> {
  try {
    if (props.action === "edit" && props.id) {
      const tp = await patchThirdparty(props.id, thirdParty.value);
      return Promise.resolve(tp);
    } else if (props.action === "addContact" || props.action === "create") {
      const tp = await createThirdParty(thirdParty.value);
      emit("onThirdPartyCreated", { thirdParty: tp });
      return Promise.resolve(tp);
    }
  } catch (e: unknown) {
    if (isValidationException<WriteThirdPartyViolationMap>(e)) {
      violations.setValidationException(e);
    } else {
      toast.error("An error occurred while creating the third party");
    }
    throw e;
  }
  throw "'action' is not edit with and id, or addContact or create";
}
</script>

<style scoped lang="scss">
.was-validated-force {
  display: block;
}

.parent-info {
  margin-bottom: 1rem;
}

.child-info {
  display: flex;
  justify-content: space-between;

  .input-section {
    width: 49%;
  }
}
</style>
