<script lang="ts">
  import { resolve } from "$app/paths";
  import { m } from "$i18n/messages.js";
  import type { DecryptedAppointment } from "$lib/client/appointment-crypto";
  import * as Alert from "$lib/components/ui/alert";
  import { AppointmentDetails } from "$lib/components/ui/appointment-details";
  import { Badge } from "$lib/components/ui/badge";
  import { Button } from "$lib/components/ui/button";
  import * as Item from "$lib/components/ui/item";
  import { LocalizedText } from "$lib/components/ui/public";
  import { openDialog, ResponsiveDialog } from "$lib/components/ui/responsive-dialog";
  import { Skeleton } from "$lib/components/ui/skeleton";
  import { Headline } from "$lib/components/ui/typography";
  import { ROUTES } from "$lib/const/routes";
  import { publicStore } from "$lib/stores/public";
  import { toDisplayDateTime } from "$lib/utils/datetime";
  import { getCurrentTranlslation } from "$lib/utils/localizations";
  import { CircleAlert } from "@lucide/svelte";
  import { onMount } from "svelte";
  import { toast } from "svelte-sonner";
  import { appointmentStatusToBadge } from "./utils";

  let channels = $derived($publicStore.channels);
  let tenant = $derived($publicStore.tenant);
  let step: "loading" | "list" | "error" = $state("loading");
  let appointments: DecryptedAppointment[] = $state([]);
  let cancelling: DecryptedAppointment | undefined = $state();
  let isCancelling = $state(false);

  onMount(() => {
    getAppointments();
  });

  const getAppointments = async () => {
    if ($publicStore.crypto?.isClientAuthenticated() && tenant) {
      appointments = await $publicStore.crypto.getMyAppointments(tenant.id);
      step = "list";
    }
  };

  const cancelAppointment = async () => {
    if (!cancelling || !tenant) return;

    isCancelling = true;
    await $publicStore.crypto
      ?.cancelAppointmentByClient({
        appointment: cancelling.id,
        tenant: tenant.id,
        name: cancelling.name,
        phone: cancelling.phone,
        email: cancelling.email,
      })
      .then(() => {
        getAppointments();
        toast.success(m["clients.appointments.cancel.success"]());
        cancelling = undefined;
      })
      .catch(() => {
        toast.error(m["clients.appointments.cancel.error"]());
      })
      .finally(() => {
        isCancelling = false;
      });
  };
</script>

<div class="flex flex-col gap-3">
  <Headline level="h2" style="h3">{m["clients.appointments.title"]()}</Headline>
  {#if step === "loading"}
    <div class="flex flex-col gap-1">
      <Skeleton class="h-20 opacity-60" />
      <Skeleton class="h-20 opacity-40" />
      <Skeleton class="h-20 opacity-20" />
    </div>
    <Skeleton class="h-8 w-30 self-end" />
  {:else if step === "list"}
    {#if appointments.length > 0}
      <div class="flex flex-col gap-1">
        {#each appointments as item (item)}
          {@const channel = channels?.find((it) => it.id === item.channelId)}
          <Item.Root variant="outline">
            <Item.Content>
              <Item.Title>
                {#if channel}
                  <LocalizedText translations={channel.names} />
                {/if}
                {@const badge = appointmentStatusToBadge(item.status)}
                {#if badge}
                  <Badge>{badge.label.toLocaleUpperCase()}</Badge>
                {/if}
              </Item.Title>
              <Item.Description>
                {toDisplayDateTime(new Date(item.appointmentDate))}
              </Item.Description>
            </Item.Content>
            <Item.Actions>
              <Button
                variant="outline"
                size="sm"
                onclick={() => {
                  cancelling = item;
                  openDialog("cancel-appointment");
                }}
              >
                {m["clients.appointments.cancel.action"]()}
              </Button>
            </Item.Actions>
          </Item.Root>
        {/each}
      </div>
    {:else}
      {m["clients.appointments.empty"]()}
    {/if}
    <Button href={resolve(ROUTES.MAIN)} class="self-end">
      {m["public.bookAppointment"]()}
    </Button>
  {:else if step === "error"}
    <Alert.Root variant="destructive">
      <CircleAlert />
      <Alert.Title>{m["clients.appointments.error.title"]()}</Alert.Title>
      <Alert.Description>
        {m["clients.appointments.error.description"]()}
      </Alert.Description>
    </Alert.Root>
  {/if}
</div>

{#if cancelling}
  {@const channel = channels?.find((it) => it.id === cancelling?.channelId)}
  <ResponsiveDialog
    id="cancel-appointment"
    title={m["clients.appointments.cancel.title"]()}
    description={m["clients.appointments.cancel.description"]()}
    triggerHidden={true}
  >
    <AppointmentDetails
      items={[
        {
          type: "channel",
          value: channel && getCurrentTranlslation(channel.names),
        },
        {
          type: "date",
          value: new Date(cancelling.appointmentDate),
        },
      ]}
    />

    <Button
      variant="destructive"
      onclick={cancelAppointment}
      isLoading={isCancelling}
      disabled={isCancelling}
      class="mt-5 w-full"
    >
      {m["clients.appointments.cancel.action"]()}
    </Button>
  </ResponsiveDialog>
{/if}
