<script setup lang="ts">
/* global $fetch */
import { useRoute, useFetch, createError } from "nuxt/app";
import { ref, type Ref } from "vue";

import { VBtn, VForm } from "vuetify/components";
import PagedList from "~/components/pagedList.vue";
import Snowflake from "~/utils/snowflake";
import OrderView from "~/components/orderView.vue";
import EntryEditor, { type fieldDefinition } from "~/components/entryEditor.vue";

const route = useRoute();
const id = route.params.id;

const clientRequest = await useFetch(`/api/clients/${id}` as "/api/clients/:id");
if (clientRequest.error.value) throw createError(clientRequest.error.value?.data ?? "");
type Client = NonNullable<typeof clientRequest.data.value>;
const client = clientRequest.data as Ref<Client>;

const clientOrdersRequest = await useFetch(`/api/clients/${id}/orders` as "/api/clients/:id/orders");
if (clientOrdersRequest.error.value) throw createError(clientOrdersRequest.error.value?.data ?? "");
type OrderSummary = NonNullable<typeof clientOrdersRequest.data.value>;
const clientOrders = clientOrdersRequest.data as Ref<OrderSummary>;

type Order = Awaited<ReturnType<typeof useFetch<void, any, "/api/orders/:id", "get">>>["data"]["value"];

// cache
const orders = ref<Map<string, {
  loading: boolean,
  value?: Order
}>>(new Map());

for (const i of clientOrders.value)
  orders.value.set(i.id, { loading: false });

async function loadOrder(id: string) {
  const entry = orders.value.get(id);
  if (!entry) throw createError(`excepted order entry for ${id}`);
  entry.loading = true;
  // @ts-expect-error
  entry.value = await $fetch(`/api/orders/${id}` as "/api/order/:id", {
    method: "GET",
  }) as Order;
  entry.loading = false;
}

let lastPagedListVModel: Array<string> = [];

function updatePagedListVModel(element: Array<string>) {
  const justOpened = element.filter(e => !lastPagedListVModel.includes(e));
  for (const i of justOpened) loadOrder(i);
  lastPagedListVModel = element;
}

const editMode = ref<boolean>(route.query?.edit === "1");
function editorFields(): Array<fieldDefinition> {
  return [
    { key: "name", type: "text", label: "Name", value: client.value.name ?? "" },
    { key: "address", type: "text", label: "Address", value: client.value.address ?? "" },
    { key: "phone", type: "text", label: "Phone", value: client.value.phone ?? "" },
    { key: "email", type: "text", label: "E-mail", value: client.value.email ?? "" },
  ];
}

const submitting = ref<boolean>(false);

// const updateForm = ref<VForm | null>(null);
const formButton = ref<VBtn | null>(null);
const formData = ref<any>({});

function normalizeForm() {
  for (const i in formData.value)
    formData.value[i] = formData.value[i] === "" ? null : formData.value[i];
}

async function handleSubmit() {
  submitting.value = true;
  normalizeForm();
  try {
    const result = await $fetch(
      `/api/clients/${client.value.id}` as "/api/clients/:id", {
        method: "PATCH",
        body: formData.value,
      },
    );
    client.value = result;
  } catch (e) {
    console.error(e);
    submitting.value = false;
    return;
  }
  submitting.value = false;
  editMode.value = false;
}

function getCreationDate() {
  const date = new Date(Number(new Snowflake(BigInt(client.value.id)).timestamp.toString())).toLocaleDateString();
  return date;
}
</script>

<template>
  <VDialog
    v-model="editMode"
    :persistent="submitting"
    :activator="formButton as unknown as (Element | null) ?? undefined"
    width="auto"
  >
    <VCard width="400px" :loading="submitting">
      <VCardTitle>
        Edit client
      </VCardTitle>
      <VForm
        ref="updateForm"
        :disabled="submitting"
        class="px-4"
      >
        <EntryEditor
          :fields="editorFields()"
          @update-sub-model-value="(k, v) => { formData[k] = v; }"
        />
      </VForm>
      <VCardActions>
        <VBtn
          color="primary"
          @click="handleSubmit"
        >
          Submit
        </VBtn>
      </VCardActions>
    </VCard>
  </VDialog>
  <VRow>
    <VCol cols="12">
      <div
        class="text-h4"
        :class="client.name === null ? ['font-italic'] : []"
      >
        {{ client.name ?? "[none]" }}
      </div>
    </VCol>
  </VRow>
  <VRow>
    <VCol md="4" cols="12">
      <VCard class="mx-auto">
        <VList>
          <VListItem
            v-if="client.address"
            prepend-icon="mdi-map-marker"
          >
            <VListItemTitle class="text-wrap">
              {{ client.address }}
            </VListItemTitle>
          </VListItem>
          <VListItem
            v-if="client.phone"
            prepend-icon="mdi-phone"
          >
            <VListItemTitle class="text-wrap">
              {{ client.phone }}
            </VListItemTitle>
          </VListItem>
          <VListItem
            v-if="client.email"
            prepend-icon="mdi-email"
          >
            <VListItemTitle class="text-wrap">
              {{ client.email }}
            </VListItemTitle>
          </VListItem>
        </VList>
        <template #actions>
          <VBtn
            ref="formButton"
          >
            edit
          </VBtn>
        </template>
      </VCard>
      <span class="font-italic text-caption">Created {{ getCreationDate() }}</span>
    </VCol>
    <VCol cols="12" md="8">
      <PagedList
        :records="clientOrders"
        record-key="id"
        record-value="id"
        @update:model-value="updatePagedListVModel"
      >
        <template #title="i">
          <VRow>
            <VCol>{{ new Date(Number(new Snowflake(BigInt((i.record.id))).timestamp)).toLocaleDateString() }}</VCol>
            <VCol>{{ i.record.value }} PLN</VCol>
            <VCol>
              {{ i.record.imported_products_count }}
              products,
              {{ i.record.work_count }}
              works
            </VCol>
          </VRow>
        </template>
        <template #text="i">
          <VProgressLinear
            :height="orders.get(i.record.id)?.loading ?? true ? undefined : 0"
            absolute
            :progress="orders.get(i.record.id)?.loading ?? true"
            :indeterminate="orders.get(i.record.id)?.loading ?? true"
          />
          <OrderView :order="orders.get(i.record.id)?.value" />
        </template>
      </PagedList>
    </VCol>
  </VRow>
</template>
