<script setup>
import { computed, ref, onMounted, onBeforeUnmount, watch, nextTick } from 'vue';

const props = defineProps({
    reservedAccounts: {
        type: Array,
        default: () => [],
    },
    layout: {
        type: String,
        default: 'stack',
    },
    compact: {
        type: Boolean,
        default: false,
    },
    emptyText: {
        type: String,
        default: 'No reserved account assigned yet.',
    },
    showStatus: {
        type: Boolean,
        default: true,
    },
});

const copiedKey = ref('');
const activeIndex = ref(0);
const carouselContainer = ref(null);

const normalizeProviderLabel = (value) => {
    const raw = String(value || '').trim();
    if (!raw) return 'Provider';

    const cleaned = raw.replace(/\bbank\b/gi, '').replace(/\s{2,}/g, ' ').trim();

    return cleaned || 'Provider';
};

const accountCards = computed(() => {
    return (props.reservedAccounts || []).flatMap((record) => {
        const entries = normalizeEntries(record?.accounts_json);

        return entries.map((entry, index) => ({
            key: `${record.id}-${index}`,
            status: String(record?.status || 'inactive'),
            accountReference: String(record?.account_reference || ''),
            bankName: normalizeProviderLabel(entry?.bankName || entry?.bank_name || entry?.bank || ''),
            accountNumber: String(entry?.accountNumber || entry?.account_number || ''),
            accountName: String(entry?.accountName || entry?.account_name || entry?.customerName || ''),
            bankCode: String(entry?.bankCode || entry?.bank_code || ''),
        }));
    });
});

const hasAccounts = computed(() => accountCards.value.length > 0);

const badgeClass = (status) => {
    return String(status || '').toLowerCase() === 'active'
        ? 'border-emerald-200 bg-emerald-50 text-emerald-700'
        : 'border-slate-200 bg-slate-100 text-slate-600';
};

const badgeLabel = (status) => {
    return String(status || '').toLowerCase() === 'active' ? 'Active' : 'Inactive';
};

const bankInitials = (name) => {
    return String(name || 'P')
        .split(' ')
        .filter(Boolean)
        .map((part) => part[0])
        .join('')
        .slice(0, 2)
        .toUpperCase();
};

const canShowDots = computed(() => props.layout === 'carousel' && accountCards.value.length > 1);

const clampIndex = (index) => {
    const max = Math.max(accountCards.value.length - 1, 0);

    return Math.min(Math.max(index, 0), max);
};

const updateActiveIndexFromScroll = () => {
    if (props.layout !== 'carousel') {
        activeIndex.value = 0;

        return;
    }

    const element = carouselContainer.value;
    if (!element) {
        return;
    }

    const card = element.querySelector('[data-carousel-card="1"]');
    if (!card) {
        activeIndex.value = 0;

        return;
    }

    const style = window.getComputedStyle(element);
    const gap = Number.parseFloat(style.columnGap || style.gap || '0') || 0;
    const step = card.clientWidth + gap;
    if (step <= 0) {
        activeIndex.value = 0;

        return;
    }

    activeIndex.value = clampIndex(Math.round(element.scrollLeft / step));
};

const onCarouselScroll = () => {
    updateActiveIndexFromScroll();
};

const onWindowResize = () => {
    updateActiveIndexFromScroll();
};

const scrollToIndex = (index) => {
    const element = carouselContainer.value;
    if (!element) {
        return;
    }

    const card = element.querySelector('[data-carousel-card="1"]');
    if (!card) {
        return;
    }

    const style = window.getComputedStyle(element);
    const gap = Number.parseFloat(style.columnGap || style.gap || '0') || 0;
    const step = card.clientWidth + gap;

    element.scrollTo({
        left: clampIndex(index) * step,
        behavior: 'smooth',
    });
};

const copyValue = async (value, key) => {
    const text = String(value || '').trim();
    if (text === '') {
        return;
    }

    try {
        if (navigator?.clipboard?.writeText) {
            await navigator.clipboard.writeText(text);
        } else {
            fallbackCopy(text);
        }
    } catch {
        fallbackCopy(text);
    }

    copiedKey.value = key;
    window.setTimeout(() => {
        if (copiedKey.value === key) {
            copiedKey.value = '';
        }
    }, 1400);
};

const fallbackCopy = (text) => {
    const textarea = document.createElement('textarea');
    textarea.value = text;
    textarea.setAttribute('readonly', '');
    textarea.style.position = 'absolute';
    textarea.style.left = '-9999px';
    document.body.appendChild(textarea);
    textarea.select();
    document.execCommand('copy');
    document.body.removeChild(textarea);
};

const normalizeEntries = (raw) => {
    const value = parseMaybeJson(raw);

    if (Array.isArray(value)) {
        return value;
    }

    if (value && typeof value === 'object') {
        if (Array.isArray(value.accounts)) {
            return value.accounts;
        }

        if (hasAccountShape(value)) {
            return [value];
        }
    }

    return [];
};

const parseMaybeJson = (value) => {
    if (typeof value !== 'string') {
        return value;
    }

    try {
        return JSON.parse(value);
    } catch {
        return value;
    }
};

const hasAccountShape = (value) => {
    return Boolean(
        value?.accountNumber
        || value?.account_number
        || value?.bankName
        || value?.bank_name
    );
};

onMounted(() => {
    if (typeof window !== 'undefined') {
        window.addEventListener('resize', onWindowResize);
    }

    updateActiveIndexFromScroll();
});

onBeforeUnmount(() => {
    if (typeof window !== 'undefined') {
        window.removeEventListener('resize', onWindowResize);
    }
});

watch(
    () => [props.layout, accountCards.value.length],
    async () => {
        await nextTick();
        updateActiveIndexFromScroll();
    }
);
</script>

<template>
    <div v-if="layout === 'carousel'">
        <div
            v-if="!hasAccounts"
            class="rounded-xl border border-dashed border-slate-300 px-3 py-3 text-sm text-slate-500"
        >
            {{ emptyText }}
        </div>

        <div
            v-else
            ref="carouselContainer"
            class="-mx-1 flex snap-x snap-mandatory gap-2 overflow-x-auto px-1 pb-1"
            @scroll.passive="onCarouselScroll"
        >
            <div
                v-for="card in accountCards"
                :key="card.key"
                data-carousel-card="1"
                class="snap-start rounded-xl border border-slate-200 bg-white shadow-sm"
                :class="compact ? 'min-w-[78%] px-3 py-2.5' : 'min-w-[84%] px-3 py-2.5'"
            >
                <div class="flex items-center justify-between gap-3">
                    <div class="flex min-w-0 items-center gap-2.5">
                        <div class="inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-slate-100 text-[10px] font-semibold text-slate-700">
                            {{ bankInitials(card.bankName) }}
                        </div>
                        <div class="min-w-0">
                            <div class="truncate text-sm font-semibold text-slate-900">{{ card.bankName }}</div>
                            <div v-if="!compact" class="truncate text-[11px] text-slate-500">{{ card.accountName || '-' }}</div>
                        </div>
                    </div>

                    <span
                        v-if="showStatus"
                        class="inline-flex shrink-0 items-center rounded-full border px-2 py-0.5 text-[10px] font-semibold"
                        :class="badgeClass(card.status)"
                    >
                        {{ badgeLabel(card.status) }}
                    </span>
                </div>

                <div class="mt-2 flex items-end justify-between gap-2">
                    <div class="min-w-0">
                        <div class="text-[10px] uppercase tracking-wide text-slate-500">Account Number</div>
                        <div class="truncate text-[15px] font-semibold tracking-[0.02em] text-slate-900">
                            {{ card.accountNumber || '-' }}
                        </div>
                    </div>
                    <button
                        type="button"
                        class="inline-flex items-center justify-center rounded-md border border-slate-300 bg-white text-slate-700 hover:bg-slate-50 disabled:cursor-not-allowed disabled:opacity-50"
                        :class="compact ? 'h-7 w-7' : 'px-2.5 py-1 text-[11px] font-semibold'"
                        :disabled="!card.accountNumber"
                        @click="copyValue(card.accountNumber, `num-${card.key}`)"
                    >
                        <template v-if="compact">
                            <span class="text-[12px] font-semibold">{{ copiedKey === `num-${card.key}` ? '✓' : '⎘' }}</span>
                            <span class="sr-only">{{ copiedKey === `num-${card.key}` ? 'Copied' : 'Copy account number' }}</span>
                        </template>
                        <template v-else>
                            {{ copiedKey === `num-${card.key}` ? 'Copied' : 'Copy' }}
                        </template>
                    </button>
                </div>

                <div v-if="!compact" class="mt-1.5 truncate text-[11px] text-slate-500">
                    Ref: {{ card.accountReference || '-' }}
                    <span v-if="card.bankCode"> • Code: {{ card.bankCode }}</span>
                </div>
            </div>
        </div>

        <div v-if="canShowDots" class="mt-2 flex items-center justify-center gap-1.5">
            <button
                v-for="(_, index) in accountCards"
                :key="`dot-${index}`"
                type="button"
                class="h-1.5 rounded-full transition-all"
                :class="activeIndex === index ? 'w-4 bg-slate-700' : 'w-1.5 bg-slate-300'"
                @click="scrollToIndex(index)"
            >
                <span class="sr-only">Go to account {{ index + 1 }}</span>
            </button>
        </div>
    </div>

    <div v-else class="space-y-2.5">
        <div
            v-if="!hasAccounts"
            class="rounded-xl border border-dashed border-slate-300 px-3 py-3 text-sm text-slate-500"
        >
            {{ emptyText }}
        </div>

        <div
            v-for="card in accountCards"
            :key="card.key"
            class="rounded-xl border border-slate-200 bg-white px-3 py-2.5"
        >
            <div class="flex items-center justify-between gap-3">
                <div class="flex min-w-0 items-center gap-2.5">
                    <div class="inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-slate-100 text-[11px] font-semibold text-slate-700">
                        {{ bankInitials(card.bankName) }}
                    </div>
                    <div class="min-w-0">
                        <div class="truncate text-sm font-semibold text-slate-900">{{ card.bankName }}</div>
                        <div class="truncate text-[11px] text-slate-500">{{ card.accountName || '-' }}</div>
                    </div>
                </div>

                <span
                    v-if="showStatus"
                    class="inline-flex shrink-0 items-center rounded-full border px-2 py-0.5 text-[10px] font-semibold"
                    :class="badgeClass(card.status)"
                >
                    {{ badgeLabel(card.status) }}
                </span>
            </div>

            <div class="mt-2 grid grid-cols-[1fr_auto] items-center gap-2 rounded-lg border border-slate-200 bg-slate-50 px-2.5 py-2">
                <div class="min-w-0">
                    <div class="text-[10px] uppercase tracking-wide text-slate-500">Account Number</div>
                    <div class="truncate text-[15px] font-semibold tracking-[0.02em] text-slate-900">
                        {{ card.accountNumber || '-' }}
                    </div>
                </div>
                <button
                    type="button"
                    class="inline-flex items-center justify-center rounded-md border border-slate-300 bg-white px-2.5 py-1 text-[11px] font-semibold text-slate-700 hover:bg-slate-50 disabled:cursor-not-allowed disabled:opacity-50"
                    :disabled="!card.accountNumber"
                    @click="copyValue(card.accountNumber, `num-${card.key}`)"
                >
                    {{ copiedKey === `num-${card.key}` ? 'Copied' : 'Copy' }}
                </button>
            </div>

            <div class="mt-1.5 flex items-center justify-between gap-2 text-[11px] text-slate-500">
                <div class="truncate">
                    Ref: {{ card.accountReference || '-' }}
                    <span v-if="card.bankCode">• Code: {{ card.bankCode }}</span>
                </div>
                <button
                    type="button"
                    class="inline-flex shrink-0 items-center rounded-md border border-slate-200 bg-white px-2 py-1 text-[10px] font-semibold text-slate-600 hover:bg-slate-50 disabled:cursor-not-allowed disabled:opacity-50"
                    :disabled="!card.accountName"
                    @click="copyValue(card.accountName, `name-${card.key}`)"
                >
                    {{ copiedKey === `name-${card.key}` ? 'Name Copied' : 'Copy Name' }}
                </button>
            </div>
        </div>
    </div>
</template>
