<script setup lang="ts">
import { useForm, usePage, router } from '@inertiajs/vue3';
import { useEcho, echoIsConfigured, configureEcho } from '@laravel/echo-vue';
import { Paperclip, Info } from '@lucide/vue';
import { ref, computed, watch } from 'vue';
import { route } from 'ziggy-js';

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'],
    });
}

const fileInput = ref<HTMLInputElement | null>(null);

const form = useForm({
    content: '',
    media: [] as File[],
});

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

function formatTimestamp(isoString: string): { full: string; time: string } {
    const date = new Date(isoString);

    return {
        full: date.toLocaleString(),
        time: date.toLocaleTimeString([], {
            hour: '2-digit',
            minute: '2-digit',
            hour12: false,
        }),
    };
}

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

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

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

function parseMessageContent(message: {
    content: string;
    subject_id?: number | null;
    subject_type?: string | null;
    subject?: any;
}) {
    let content = message.content;

    // 1. Replace <user:id> placeholders with links to their dynamic profile
    const userRegex = /<user:(\d+)>/g;
    content = content.replace(userRegex, (match, userId) => {
        const user = participantsById.value[Number(userId)];

        if (user) {
            const url = route('dynamics.users.show', [props.dynamicId, Number(userId)]);

            return `<a href="${url}" class="c-chat__user-link font-semibold text-blue-500 hover:underline">${
                user.pivot?.display_name ?? user.name
            }</a>`;
        }

        return `User #${userId}`;
    });

    // 2. Link subjects if found in the text
    if (message.subject_id && message.subject_type) {
        if (
            message.subject_type === 'mutation' ||
            message.subject_type === 'ledger'
        ) {
            const ledgerId =
                message.subject_type === 'mutation'
                    ? message.subject?.ledger_id
                    : message.subject?.id;

            const ledgerName =
                message.subject_type === 'mutation'
                    ? message.subject?.ledger?.name
                    : message.subject?.name;

            if (ledgerId && ledgerName) {
                const ledgerUrl = route('dynamics.ledgers.show', [
                    props.dynamicId,
                    ledgerId,
                ]);

                const escapedName = ledgerName.replace(
                    /[-\/\\^$*+?.()|[\]{}]/g,
                    '\\$&',
                );

                const nameRegex = new RegExp(`"${escapedName}"`, 'g');
                content = content.replace(
                    nameRegex,
                    `"<a href="${ledgerUrl}" class="c-chat__subject-link font-semibold text-blue-500 hover:underline">${ledgerName}</a>"`,
                );
            }
        }
    }

    return content;
}

function handleFileChange(event: Event) {
    const files = (event.target as HTMLInputElement).files;

    if (files) {
        for (let i = 0; i < files.length; i++) {
            form.media.push(files[i]);
        }
    }
}

function removeFile(index: number) {
    form.media.splice(index, 1);
}

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;
}

function submit() {
    form.post(route('chats.messages.store', props.chat.id), {
        preserveScroll: true,
        onSuccess: () => {
            form.reset();

            if (fileInput.value) {
                fileInput.value.value = '';
            }
        },
    });
}

// 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 -->
                <template v-if="message.user">
                    <div class="c-chat__message-header">
                        <span class="c-chat__message-author">{{
                            message.user.name
                        }}</span>
                        <span
                            class="c-chat__message-time"
                            :title="formatTimestamp(message.created_at).full"
                        >
                            {{ formatTimestamp(message.created_at).time }}
                        </span>
                    </div>
                    <p class="c-chat__message-text" v-html="parseMessageContent(message)"></p>

                    <!-- Attached Media Display -->
                    <div
                        v-if="message.media && message.media.length > 0"
                        class="c-chat__message-media"
                    >
                        <div
                            v-for="item in message.media"
                            :key="item.id"
                            class="c-chat__media-item"
                        >
                            <img
                                v-if="item.mime_type.startsWith('image/')"
                                :src="item.url"
                                :alt="item.file_name"
                                class="c-chat__image cursor-pointer transition-opacity hover:opacity-90"
                                @click="openLightbox(item.url, item.mime_type)"
                            />
                            <div
                                v-else-if="item.mime_type.startsWith('video/')"
                                class="relative cursor-pointer transition-opacity hover:opacity-90"
                                @click="openLightbox(item.url, item.mime_type)"
                            >
                                <video
                                    :src="item.url"
                                    class="c-chat__video"
                                ></video>
                                <div class="c-chat__play-overlay">▶</div>
                            </div>
                        </div>
                    </div>
                </template>

                <!-- Subtle Activity Log System Message -->
                <template v-else>
                    <div class="c-chat__system-inner">
                        <Info class="c-chat__system-icon" />
                        <span
                            class="c-chat__system-text"
                            v-html="parseMessageContent(message)"
                        ></span>
                        <span
                            class="c-chat__system-time"
                            :title="formatTimestamp(message.created_at).full"
                        >
                            {{ formatTimestamp(message.created_at).time }}
                        </span>
                    </div>
                </template>
            </div>
            <div v-if="messages.length === 0" class="c-chat__empty">
                No messages yet.
            </div>
        </div>
        <form @submit.prevent="submit" class="c-chat__form">
            <div class="c-chat__form-group">
                <label for="content" class="c-chat__label">Message</label>
                <textarea
                    v-model="form.content"
                    id="content"
                    rows="3"
                    class="c-chat__textarea"
                    placeholder="Type a message... (Press Enter to send, Shift+Enter for newline)"
                    @keydown.enter.exact.prevent="submit"
                ></textarea>
                <div v-if="form.errors.content" class="c-chat__error">
                    {{ form.errors.content }}
                </div>

                <!-- Attachment Button & Hidden Input -->
                <div class="c-chat__attachment-container">
                    <button
                        type="button"
                        @click="fileInput?.click()"
                        class="c-chat__attach-btn"
                    >
                        <Paperclip class="c-chat__attach-icon" />
                        Attach Photos/Videos
                    </button>
                    <input
                        ref="fileInput"
                        type="file"
                        multiple
                        accept="image/*,video/*"
                        class="hidden"
                        @change="handleFileChange"
                    />
                </div>

                <!-- Previews List -->
                <div v-if="form.media.length > 0" class="c-chat__preview-list">
                    <div
                        v-for="(file, index) in form.media"
                        :key="index"
                        class="c-chat__preview-item"
                    >
                        <span class="c-chat__preview-name">{{
                            file.name
                        }}</span>
                        <button
                            type="button"
                            @click="removeFile(index)"
                            class="c-chat__preview-remove"
                        >
                            ✕
                        </button>
                    </div>
                </div>
            </div>
            <div class="c-chat__submit-box">
                <button
                    type="submit"
                    :disabled="form.processing"
                    class="c-chat__button"
                >
                    Send
                </button>
            </div>
        </form>

        <!-- 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>
