<script setup lang="ts">
import { usePage } from '@inertiajs/vue3';
import { useEcho, echoIsConfigured, configureEcho } from '@laravel/echo-vue';
import { ref, computed, watch } from 'vue';
import { route } from 'ziggy-js';
import ChatInput from './chat/ChatInput.vue';
import ChatSystemMessage from './chat/ChatSystemMessage.vue';
import ChatUserMessage from './chat/ChatUserMessage.vue';

const props = withDefaults(
    defineProps<{
        chat: {
            id: number;
            messages?: Array<{
                id: number;
                user: { id: number; name: string } | null;
                content: string;
                created_at: string;
                subject_id?: number | null;
                subject_type?: string | null;
                subject?: any;
                media?: Array<{
                    id: number;
                    url: string;
                    file_name: string;
                    mime_type: string;
                }>;
            }>;
        };
        participants?: Array<{
            id: number;
            name: string;
            pivot?: {
                display_name: string | null;
            } | null;
        }>;
        dynamicId: string;
        ledgerId?: string | null;
        initialMessages?: {
            data: Array<any>;
            next_page_url?: string | null;
            links?: {
                next: string | null;
            } | null;
            current_page?: number;
            meta?: {
                current_page: number;
            } | null;
        } | null;
    }>(),
    {
        participants: () => [],
        initialMessages: null,
        ledgerId: null,
    }
);

const getNextPageUrl = (paginator: any) => {
    return paginator?.links?.next ?? paginator?.next_page_url ?? null;
};

const getCurrentPage = (paginator: any) => {
    return paginator?.meta?.current_page ?? paginator?.current_page ?? 1;
};

const messages = ref(
    props.initialMessages
        ? props.initialMessages.data.slice().reverse()
        : (props.chat.messages || []).slice()
);
const nextPageUrl = ref(getNextPageUrl(props.initialMessages));
const currentPageNum = ref(1);

watch(
    () => props.initialMessages,
    (newVal) => {
        if (newVal && getCurrentPage(newVal) === 1) {
            messages.value = newVal.data.slice().reverse();
            nextPageUrl.value = getNextPageUrl(newVal);
            currentPageNum.value = 1;
        }
    },
    { deep: true }
);

watch(
    () => props.chat.messages,
    (newVal) => {
        if (!props.initialMessages && newVal) {
            messages.value = newVal.slice();
        }
    },
    { deep: true }
);

function loadMoreMessages() {
    if (!nextPageUrl.value) {
        return;
    }

    currentPageNum.value++;

    const apiRouteName = props.ledgerId ? 'dynamics.ledgers.messages' : 'dynamics.messages';
    const apiParams = props.ledgerId ? [props.dynamicId, props.ledgerId] : [props.dynamicId];
    const url = route(apiRouteName, [...apiParams, { page: currentPageNum.value }]);

    fetch(url)
        .then((res) => res.json())
        .then((json) => {
            const data = json?.data || [];
            messages.value = [...data.slice().reverse(), ...messages.value];
            nextPageUrl.value = getNextPageUrl(json);
        })
        .catch((err) => {
            console.error('Failed to load older messages:', err);
            currentPageNum.value--;
        });
}

if (!echoIsConfigured()) {
    configureEcho({
        broadcaster: 'reverb',
        key: import.meta.env.VITE_REVERB_APP_KEY || 'mock-key',
        wsHost: import.meta.env.VITE_REVERB_HOST || 'localhost',
        wsPort: import.meta.env.VITE_REVERB_PORT
            ? Number(import.meta.env.VITE_REVERB_PORT)
            : 8080,
        wssPort: import.meta.env.VITE_REVERB_PORT
            ? Number(import.meta.env.VITE_REVERB_PORT)
            : 8080,
        forceTLS: false,
        enabledTransports: ['ws', 'wss'],
    });
}

useEcho(`chats.${props.chat.id}`, 'MessageSent', (e: any) => {
    messages.value.push(e.message);
});

const participantsById = computed(() => {
    const list = props.participants || [];

    return list.reduce(
        (acc, p) => {
            acc[p.id] = p;

            return acc;
        },
        {} as Record<
            number,
            {
                id: string;
                name: string;
                pivot?: { display_name: string | null } | null;
            }
        >,
    );
});

const currentUser = computed(() => usePage().props.auth?.user);

function isOwnMessage(messageUserId: number | null): boolean {
    if (messageUserId === null) {
        return false;
    }

    return currentUser.value && currentUser.value.id === messageUserId;
}

// Lightbox Modal state
const activeLightboxUrl = ref<string | null>(null);
const activeLightboxType = ref<'image' | 'video' | null>(null);

function openLightbox(url: string, mimeType: string) {
    activeLightboxUrl.value = url;
    activeLightboxType.value = mimeType.startsWith('image/')
        ? 'image'
        : 'video';
}

function closeLightbox() {
    activeLightboxUrl.value = null;
    activeLightboxType.value = null;
}
</script>

<template>
    <div class="c-chat">
        <h4 class="c-chat__title">Chat</h4>
        <div class="c-chat__list">
            <div v-if="nextPageUrl" class="c-chat__load-more">
                <button @click="loadMoreMessages" class="c-chat__load-more-btn">
                    Load More
                </button>
            </div>
            <div
                v-for="message in messages"
                :key="message.id"
                :class="[
                    'c-chat__message',
                    {
                        'c-chat__message--system': message.user === null,
                        'c-chat__message--own': isOwnMessage(message.user?.id),
                        'c-chat__message--other': message.user !== null && !isOwnMessage(message.user?.id)
                    },
                ]"
            >
                <!-- Standard User Chat Message -->
                <ChatUserMessage
                    v-if="message.user"
                    :message="message"
                    :participants-by-id="participantsById"
                    :dynamic-id="dynamicId"
                    @open-lightbox="openLightbox"
                />

                <!-- Subtle Activity Log System Message -->
                <ChatSystemMessage
                    v-else
                    :message="message"
                    :participants-by-id="participantsById"
                    :dynamic-id="dynamicId"
                />
            </div>
            <div v-if="messages.length === 0" class="c-chat__empty">
                No messages yet.
            </div>
        </div>

        <!-- Cohesive Chat input Form -->
        <ChatInput :chat-id="chat.id" />

        <!-- Gorgeous Dark Lightbox Modal -->
        <div v-if="activeLightboxUrl" class="c-lightbox" @click="closeLightbox">
            <button @click="closeLightbox" class="c-lightbox__close">✕</button>
            <div class="c-lightbox__content" @click.stop>
                <img
                    v-if="activeLightboxType === 'image'"
                    :src="activeLightboxUrl"
                    class="c-lightbox__image"
                />
                <video
                    v-else-if="activeLightboxType === 'video'"
                    :src="activeLightboxUrl"
                    controls
                    autoplay
                    class="c-lightbox__video"
                ></video>
            </div>
        </div>
    </div>
</template>

<style scoped>
@reference "../../css/app.css";

.c-chat {
    @apply flex flex-col h-[500px];
    background-color: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.c-chat__title {
    @apply p-4 font-bold border-b text-sm;
    border-color: var(--border);
    color: var(--foreground);
}

.c-chat__list {
    @apply flex-1 overflow-y-auto p-4 space-y-4;
}

.c-chat__load-more {
    @apply flex justify-center py-2;
}

.c-chat__load-more-btn {
    @apply text-xs font-semibold text-blue-500 hover:underline;
}

.c-chat__message {
    @apply max-w-[75%] p-3 rounded-lg flex flex-col gap-1;
}

.c-chat__message--own {
    @apply self-end;
    background-color: var(--primary);
    color: var(--primary-foreground);
    border-bottom-right-radius: 0;

    .c-chat__message-author {
        @apply hidden;
    }

    .c-chat__message-time {
        @apply text-blue-100;
    }

    .c-chat__message-text {
        color: var(--primary-foreground);
    }
}

.c-chat__message--other {
    @apply self-start;
    background-color: var(--muted);
    color: var(--muted-foreground);
    border-bottom-left-radius: 0;
}

.c-chat__message--system {
    @apply self-center max-w-full w-full bg-transparent border-0 p-0 text-center gap-0;
}

.c-chat__message-header {
    @apply flex items-baseline gap-2 mb-1;
}

.c-chat__message-author {
    @apply font-semibold text-xs;
}

.c-chat__message-time {
    @apply text-[10px];
    color: var(--muted-foreground);
}

.c-chat__message-text {
    @apply text-sm break-words whitespace-pre-wrap leading-relaxed;
}

.c-chat__message-media {
    @apply mt-2 flex flex-wrap gap-2;
}

.c-chat__media-item {
    @apply max-w-[120px] overflow-hidden rounded border border-black dark:border-gray-600 bg-black;
}

.c-chat__image {
    @apply h-auto max-h-[80px] w-full object-cover;
}

.c-chat__video {
    @apply h-auto max-h-[80px] w-full;
}

.c-chat__play-overlay {
    @apply absolute inset-0 flex items-center justify-center bg-black/40 text-lg font-bold text-white;
}

.c-chat__system-inner {
    @apply inline-flex items-center gap-2 bg-neutral-100 dark:bg-neutral-900/30 px-3 py-1 rounded-full text-xs text-neutral-500 dark:text-neutral-400;
}

.c-chat__system-icon {
    @apply size-3.5;
}

.c-chat__system-text {
    @apply font-medium leading-relaxed;
}

.c-chat__system-time {
    @apply text-[10px] opacity-75 ml-1;
}

.c-chat__empty {
    @apply text-center text-xs py-8;
    color: var(--muted-foreground);
}

.c-chat__form {
    @apply p-4 border-t flex flex-col gap-2 bg-neutral-50 dark:bg-neutral-900/10;
    border-color: var(--border);
}

.c-chat__form-group {
    @apply relative flex flex-col gap-1;
}

.c-chat__label {
    @apply sr-only;
}

.c-chat__textarea {
    @apply w-full rounded border p-2 text-sm resize-none focus:outline-none focus:ring-1 focus:ring-blue-500 dark:bg-neutral-900 dark:border-neutral-800;
    color: var(--foreground);
    border-color: var(--border);
}

.c-chat__error {
    @apply text-xs text-red-500 mt-1;
}

.c-chat__attachment-container {
    @apply flex items-center mt-1;
}

.c-chat__attach-btn {
    @apply inline-flex items-center gap-1.5 text-xs text-neutral-500 hover:text-neutral-900 dark:hover:text-neutral-100 transition-colors;
}

.c-chat__attach-icon {
    @apply size-3.5;
}

.c-chat__preview-list {
    @apply mt-2 flex flex-wrap gap-2;
}

.c-chat__preview-item {
    @apply inline-flex items-center gap-2 bg-neutral-100 dark:bg-neutral-900/50 px-2 py-1 rounded text-xs;
}

.c-chat__preview-name {
    @apply max-w-[150px] truncate text-neutral-600 dark:text-neutral-400;
}

.c-chat__preview-remove {
    @apply text-neutral-400 hover:text-red-500 transition-colors;
}

.c-chat__submit-box {
    @apply flex justify-end mt-1;
}

.c-chat__button {
    @apply inline-flex items-center justify-center rounded-md border border-transparent bg-gray-800 px-4 py-2 text-xs font-semibold tracking-widest text-white uppercase transition duration-150 ease-in-out hover:bg-gray-700 focus:bg-gray-700 focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 focus:outline-none active:bg-gray-900 dark:bg-gray-200 dark:text-gray-800 dark:hover:bg-white dark:focus:bg-white dark:focus:ring-offset-gray-800 dark:active:bg-gray-300;
}
</style>
