<script setup>
import { onBeforeMount, watch, computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import SkeletonDescriptor from 'components/ui/SkeletonDescriptor.vue';
import { useArrayData } from 'composables/useArrayData';
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import { useState } from 'src/composables/useState';
import { useRoute, useRouter } from 'vue-router';
import { useClipboard } from 'src/composables/useClipboard';
import VnMoreOptions from './VnMoreOptions.vue';

const $props = defineProps({
    url: {
        type: String,
        default: '',
    },
    filter: {
        type: Object,
        default: null,
    },
    title: {
        type: String,
        default: '',
    },
    subtitle: {
        type: Number,
        default: null,
    },
    dataKey: {
        type: String,
        default: null,
    },
    summary: {
        type: Object,
        default: null,
    },
    width: {
        type: String,
        default: 'md-width',
    },
});

const state = useState();
const route = useRoute();
const router = useRouter();
const { t } = useI18n();
const { copyText } = useClipboard();
const { viewSummary } = useSummaryDialog();
let arrayData;
let store;
let entity;
const isLoading = ref(false);
const isSameDataKey = computed(() => $props.dataKey === route.meta.moduleName);
const DESCRIPTOR_PROXY = 'DescriptorProxy';
const moduleName = ref();
const isSameModuleName = route.matched[1].meta.moduleName !== moduleName.value;
defineExpose({ getData });

onBeforeMount(async () => {
    arrayData = useArrayData($props.dataKey, {
        url: $props.url,
        userFilter: $props.filter,
        skip: 0,
        oneRecord: true,
    });
    store = arrayData.store;
    entity = computed(() => {
        const data = store.data ?? {};
        if (data) emit('onFetch', data);
        return data;
    });

    // It enables to load data only once if the module is the same as the dataKey
    if (!isSameDataKey.value || !route.params.id) await getData();
    watch(
        () => [$props.url, $props.filter],
        async () => {
            if (!isSameDataKey.value) await getData();
        },
    );
});

function getName() {
    let name = $props.dataKey;
    if ($props.dataKey.includes(DESCRIPTOR_PROXY)) {
        name = name.split(DESCRIPTOR_PROXY)[0];
    }
    return name;
}
const routeName = computed(() => {
    let routeName = getName();
    return `${routeName}Summary`;
});

async function getData() {
    store.url = $props.url;
    store.filter = $props.filter ?? {};
    isLoading.value = true;
    try {
        const { data } = await arrayData.fetch({ append: false, updateRouter: false });
        state.set($props.dataKey, data);
        emit('onFetch', data);
    } finally {
        isLoading.value = false;
    }
}

function getValueFromPath(path) {
    if (!path) return;
    const keys = path.toString().split('.');
    let current = entity.value;

    for (const key of keys) {
        if (current[key] === undefined) return undefined;
        else current = current[key];
    }
    return current;
}

function copyIdText(id) {
    copyText(id, {
        component: {
            copyValue: id,
        },
    });
}

const emit = defineEmits(['onFetch']);

const iconModule = computed(() => {
    moduleName.value = getName();
    if (isSameModuleName) {
        return router.options.routes[1].children.find((r) => r.name === moduleName.value)
            ?.meta?.icon;
    } else {
        return route.matched[1].meta.icon;
    }
});

const toModule = computed(() => {
    moduleName.value = getName();
    if (isSameModuleName) {
        return router.options.routes[1].children.find((r) => r.name === moduleName.value)
            ?.children[0]?.redirect;
    } else {
        return route.matched[1].path.split('/').length > 2
            ? route.matched[1].redirect
            : route.matched[1].children[0].redirect;
    }
});
</script>

<template>
    <div class="descriptor" data-cy="cardDescriptor">
        <template v-if="entity && !isLoading">
            <div class="header bg-primary q-pa-sm justify-between">
                <slot name="header-extra-action">
                    <QBtn
                        round
                        flat
                        dense
                        size="md"
                        :icon="iconModule"
                        color="white"
                        class="link"
                        :to="toModule"
                    >
                        <QTooltip>
                            {{ t('globals.goToModuleIndex') }}
                        </QTooltip>
                    </QBtn>
                </slot>
                <QBtn
                    @click.stop="viewSummary(entity.id, $props.summary, $props.width)"
                    round
                    flat
                    dense
                    size="md"
                    icon="preview"
                    color="white"
                    class="link"
                    v-if="summary"
                    data-cy="openSummaryBtn"
                >
                    <QTooltip>
                        {{ t('components.smartCard.openSummary') }}
                    </QTooltip>
                </QBtn>
                <RouterLink :to="{ name: routeName, params: { id: entity.id } }">
                    <QBtn
                        class="link"
                        color="white"
                        dense
                        flat
                        icon="launch"
                        round
                        size="md"
                        data-cy="goToSummaryBtn"
                    >
                        <QTooltip>
                            {{ t('components.cardDescriptor.summary') }}
                        </QTooltip>
                    </QBtn>
                </RouterLink>
                <VnMoreOptions v-if="$slots.menu">
                    <template #menu="{ menuRef }">
                        <slot name="menu" :entity="entity" :menu-ref="menuRef" />
                    </template>
                </VnMoreOptions>
            </div>
            <slot name="before" />
            <div class="body q-py-sm">
                <QList dense>
                    <QItemLabel header class="ellipsis text-h5" :lines="1">
                        <div class="title">
                            <span
                                v-if="$props.title"
                                :title="getValueFromPath(title)"
                                :data-cy="`${$attrs['data-cy'] ?? 'cardDescriptor'}_title`"
                            >
                                {{ getValueFromPath(title) ?? $props.title }}
                            </span>
                            <slot v-else name="description" :entity="entity">
                                <span
                                    :title="entity.name"
                                    :data-cy="`${$attrs['data-cy'] ?? 'cardDescriptor'}_description`"
                                    v-text="entity.name"
                                />
                            </slot>
                        </div>
                    </QItemLabel>
                    <QItem>
                        <QItemLabel
                            class="subtitle"
                            :data-cy="`${$attrs['data-cy'] ?? 'cardDescriptor'}_subtitle`"
                        >
                            #{{ getValueFromPath(subtitle) ?? entity.id }}
                        </QItemLabel>
                        <QBtn
                            round
                            flat
                            dense
                            size="sm"
                            icon="content_copy"
                            color="primary"
                            @click.stop="copyIdText(entity.id)"
                        >
                            <QTooltip>
                                {{ t('globals.copyId') }}
                            </QTooltip>
                        </QBtn>
                    </QItem>
                </QList>
                <div
                    class="list-box q-mt-xs"
                    :data-cy="`${$attrs['data-cy'] ?? 'cardDescriptor'}_listbox`"
                >
                    <slot name="body" :entity="entity" />
                </div>
            </div>
            <div class="icons">
                <slot name="icons" :entity="entity" />
            </div>
            <div class="actions justify-center" data-cy="descriptor_actions">
                <slot name="actions" :entity="entity" />
            </div>
            <slot name="after" />
        </template>
        <SkeletonDescriptor v-if="!entity || isLoading" />
    </div>
    <QInnerLoading
        :label="t('globals.pleaseWait')"
        :showing="isLoading"
        color="primary"
    />
</template>

<style lang="scss">
.body {
    background-color: var(--vn-section-color);
    .text-h5 {
        font-size: 20px;
        padding-top: 5px;
        padding-bottom: 0px;
    }
    .q-item {
        min-height: 20px;

        .link {
            margin-left: 10px;
        }
    }
    .vn-label-value {
        display: flex;
        padding: 0px 16px;
        .label {
            color: var(--vn-label-color);
            font-size: 14px;

            &:not(:has(a))::after {
                content: ':';
            }
        }
        .value {
            color: var(--vn-text-color);
            font-size: 14px;
            margin-left: 4px;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            text-align: left;
        }
        .info {
            margin-left: 5px;
        }
    }
}
</style>

<style lang="scss" scoped>
.title {
    overflow: hidden;
    text-overflow: ellipsis;
    span {
        color: var(--vn-text-color);
        font-weight: bold;
    }
}
.subtitle {
    color: var(--vn-text-color);
    font-size: 16px;
    margin-bottom: 2px;
}
.list-box {
    .q-item__label {
        color: var(--vn-label-color);
        padding-bottom: 0%;
    }
}
.descriptor {
    width: 256px;
    .header {
        display: flex;
        align-items: center;
    }
    .icons {
        margin: 0 10px;
        display: flex;
        justify-content: center;
        .q-icon {
            margin-right: 5px;
        }
    }
    .actions {
        margin: 0 5px;
        justify-content: center !important;
    }
}
</style>
<i18n>
    en:
        globals:
            copyId: Copy ID
    es:
        globals:
            copyId: Copiar ID
</i18n>
