import { DirectusClient } from '../services/directus-client.js';
import { DocumentCardView } from '../components/document-card-view.js';
import { CustomDropdown } from '../components/custom-dropdown.js';
import { DateRangePicker } from '../components/date-range-picker.js';
import { CounterAnimation } from '../components/counter-animation.js';

export class DocumentRepository {
    static PAGE_SIZE = 6;

    constructor() {
        this.gridContainer = document.getElementById('document-grid');
        this.filterWrapper = document.getElementById('tag-filter-wrapper');
        this.mobileFilterWrapper = document.getElementById('mobile-tag-filter-wrapper');
        this.searchInput = document.getElementById('doc-search');
        this.sortFilterWrapper = document.getElementById('sort-filter-wrapper');

        // Hero stat values (filled from real API data after fetch).
        this.statActiveEl = document.getElementById('stat-active-value');
        this.statUpdatesEl = document.getElementById('stat-updates-value');

        this.cards = [];
        this.paginationContainer = null;
        this.state = {
            filter: 'all',   // 'all' or a specific tag string
            search: '',
            startDate: '',
            endDate: '',
            sort: 'newest',
            page: 1,
        };
    }


    async init() {
        if (!this.gridContainer) return;
        this._bindControls();
        this._initPagination();
        try {
            const items = await DirectusClient.fetchPublished('berkas');
            this._renderCards(items);
            this._buildCategoryFilters(items);
            this._renderStats(items);
            this._applySort();
            this._applyFilters();
        } catch (err) {
            console.error(err);
            this._renderError();
            this._renderStatsError();
        }
    }

    _initPagination() {
        const pag = document.createElement('div');
        pag.id = 'doc-pagination';
        pag.className = 'doc-pagination';
        this.gridContainer.insertAdjacentElement('afterend', pag);
        this.paginationContainer = pag;
    }

    // Days within which an upload counts as a "recent update".
    static RECENT_DAYS = 30;

    // Populate the hero stats from real data:
    //   Dokumen Aktif      → number of published documents
    //   Pembaruan Terbaru  → uploads within the last RECENT_DAYS days
    _renderStats(items) {
        const active = items.length;

        const windowMs = DocumentRepository.RECENT_DAYS * 24 * 60 * 60 * 1000;
        const now = Date.now();
        const recent = items.filter(item => {
            if (!item.tanggal_upload) return false;
            const t = new Date(item.tanggal_upload).getTime();
            return !Number.isNaN(t) && now - t <= windowMs;
        }).length;

        CounterAnimation.animateValue(this.statActiveEl, active);
        CounterAnimation.animateValue(this.statUpdatesEl, recent);
    }

    _renderStatsError() {
        if (this.statActiveEl) this.statActiveEl.textContent = '—';
        if (this.statUpdatesEl) this.statUpdatesEl.textContent = '—';
    }
    /**
     * Fixed category definitions for the sidebar filter.
     * Each has a key, an i18n key for bilingual labels, and a fallback label.
     */
    static CATEGORIES = [
        { key: 'all',      i18n: 'filter_all',      label: 'Semua Berkas' },
        { key: 'skripsi',  i18n: 'filter_skripsi',  label: 'Panduan Skripsi' },
        { key: 'akademik', i18n: 'filter_akademik', label: 'Kalender Akademik' },
        { key: 'praktik',  i18n: 'filter_praktik',  label: 'Kerja Praktik' },
        { key: 'umum',     i18n: 'filter_umum',     label: 'Formulir Umum' },
    ];

    /**
     * Build category filter controls:
     *  – Desktop: sidebar buttons (hidden on mobile via CSS)
     *  – Mobile:  a <select> dropdown (hidden on desktop via CSS)
     * Both stay in sync through a shared _setFilter() helper.
     */
    _buildCategoryFilters(items) {
        if (!this.filterWrapper) return;

        // Clear skeleton placeholder.
        this.filterWrapper.innerHTML = '';

        // ── Desktop buttons ──
        const btnGroup = document.createElement('div');
        btnGroup.className = 'filter-btn-group';

        DocumentRepository.CATEGORIES.forEach(({ key, i18n, label }) => {
            const isActive = key === 'all';
            const btn = document.createElement('button');
            btn.className = 'doc-filter-btn' + (isActive ? ' active' : '');
            btn.dataset.filter = key;
            btn.textContent = (window.tpT?.(i18n)) || label;
            btn.setAttribute('data-tp-i18n', i18n);

            btn.addEventListener('click', () => this._setFilter(key));
            btnGroup.appendChild(btn);
        });

        this.filterWrapper.appendChild(btnGroup);

        // ── Mobile Custom UI Dropdown ──
        if (this.mobileFilterWrapper) {
            const dropdownOptions = DocumentRepository.CATEGORIES.map(({ key, i18n, label }) => ({
                value: key,
                i18nKey: i18n,
                text: (window.tpT?.(i18n)) || label
            }));

            this._mobileDropdown = new CustomDropdown({
                container: this.mobileFilterWrapper,
                options: dropdownOptions,
                defaultValue: this.state.filter,
                onChange: (value) => this._setFilter(value)
            });
        }

        // Store refs for syncing.
        this._filterBtnGroup = btnGroup;

        // Re-translate if i18n is active.
        window.applyTp?.(this.filterWrapper);
    }

    /**
     * Shared filter setter — keeps buttons + dropdown in sync.
     */
    _setFilter(key) {
        this.state.filter = key;
        this.state.page = 1;

        // Sync buttons.
        if (this._filterBtnGroup) {
            this._filterBtnGroup.querySelectorAll('.doc-filter-btn')
                .forEach(b => b.classList.toggle('active', b.dataset.filter === key));
        }

        // Sync custom dropdown.
        if (this._mobileDropdown && this._mobileDropdown.getValue() !== key) {
            this._mobileDropdown.setValue(key);
        }

        this._applyFilters();
    }

    _bindControls() {
        this.searchInput?.addEventListener('input', (e) => {
            this.state.search = e.target.value.toLowerCase().trim();
            this.state.page = 1;
            this._applyFilters();
        });

        // Initialize Custom Date Range Picker
        const datePickerGroup = document.getElementById('date-range-control-group');
        if (datePickerGroup) {
            this.dateRangePicker = new DateRangePicker({
                containerId: 'date-range-control-group',
                onChange: (startDate, endDate) => {
                    this.state.startDate = startDate;
                    this.state.endDate = endDate;
                    this.state.page = 1;
                    this._applyFilters();
                }
            });
            window.applyTp?.(datePickerGroup);
        }

        if (this.sortFilterWrapper) {
            const sortOptions = [
                { value: 'newest', i18nKey: 'sort_newest', text: (window.tpT?.('sort_newest')) || 'Terbaru' },
                { value: 'oldest', i18nKey: 'sort_oldest', text: (window.tpT?.('sort_oldest')) || 'Terlama' },
                { value: 'az',     i18nKey: 'sort_az',     text: (window.tpT?.('sort_az'))     || 'Nama A-Z' }
            ];

            this._sortDropdown = new CustomDropdown({
                container: this.sortFilterWrapper,
                options: sortOptions,
                defaultValue: this.state.sort,
                prefixIcon: 'fas fa-sort-amount-down',
                onChange: (value) => {
                    this.state.sort = value;
                    this.state.page = 1;
                    this._applySort();
                    this._applyFilters();
                }
            });

            window.applyTp?.(this.sortFilterWrapper);
        }
    }

    _renderCards(items) {
        this.gridContainer.innerHTML = '';

        if (items.length === 0) {
            this._renderState('repo-empty', 'fas fa-folder-open', '#cbd5e1', '#64748b',
                'state_empty', 'Belum ada dokumen yang tersedia di repositori.');
            return;
        }

        this.cards = items.map(item => {
            const view = new DocumentCardView(item);
            const element = view.render();
            this.gridContainer.appendChild(element);
            return { view, element };
        });

        // Translate the freshly-rendered card labels (Buka/Unduh Berkas).
        window.applyTp?.(this.gridContainer);
    }

    _renderError() {
        this._renderState('repo-error', 'fas fa-exclamation-triangle', '#f87171', '#ef4444',
            'state_error', 'Gagal memuat berkas. Silakan periksa koneksi internet Anda atau coba lagi nanti.');
    }

    // Build the empty/error placeholder via safe DOM APIs (no innerHTML).
    // `i18nKey` lets the Tapops i18n layer re-translate the message on toggle.
    _renderState(className, iconClass, iconColor, textColor, i18nKey, message) {
        this.cards = [];
        this.gridContainer.innerHTML = '';

        const wrapper = document.createElement('div');
        wrapper.className = className;
        Object.assign(wrapper.style, {
            gridColumn: '1 / -1',
            textAlign: 'center',
            padding: '60px 20px',
            color: textColor,
            fontWeight: '700',
            fontSize: '1rem',
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'center',
            gap: '15px',
        });

        const icon = document.createElement('i');
        icon.className = iconClass;
        Object.assign(icon.style, { fontSize: '3rem', color: iconColor });

        const span = document.createElement('span');
        if (i18nKey) span.setAttribute('data-tp-i18n', i18nKey);
        span.textContent = (window.tpT?.(i18nKey)) || message;

        wrapper.appendChild(icon);
        wrapper.appendChild(span);
        this.gridContainer.appendChild(wrapper);
    }

    _applyFilters() {
        const matched = this.cards.filter(({ view }) => this._cardMatches(view));
        const total = matched.length;

        // Handle zero-results state when cards exist but none match the filter.
        this._toggleNoResultsState(total === 0 && this.cards.length > 0);

        if (total === 0) {
            this.cards.forEach(({ element }) => { element.style.display = 'none'; });
            this._renderPagination(0, 0);
            return;
        }

        const totalPages = Math.ceil(total / DocumentRepository.PAGE_SIZE);

        // Clamp page to valid range after filter changes.
        this.state.page = Math.min(Math.max(this.state.page, 1), totalPages);

        const start = (this.state.page - 1) * DocumentRepository.PAGE_SIZE;
        const pageSet = new Set(
            matched.slice(start, start + DocumentRepository.PAGE_SIZE).map(c => c.element)
        );

        this.cards.forEach(({ element }) => {
            const show = pageSet.has(element);
            element.style.display = show ? 'flex' : 'none';
            if (show) {
                setTimeout(() => {
                    element.style.opacity = '1';
                    element.style.transform = 'translateY(0)';
                }, 10);
            } else {
                element.style.opacity = '0';
                element.style.transform = 'translateY(10px)';
            }
        });

        this._renderPagination(totalPages, total);
    }

    _toggleNoResultsState(show) {
        const existing = this.gridContainer.querySelector('.repo-no-results');
        if (show && !existing) {
            const wrapper = document.createElement('div');
            wrapper.className = 'repo-no-results';
            Object.assign(wrapper.style, {
                gridColumn: '1 / -1',
                textAlign: 'center',
                padding: '60px 20px',
                color: '#64748b',
                fontWeight: '700',
                fontSize: '1rem',
                display: 'flex',
                flexDirection: 'column',
                alignItems: 'center',
                gap: '15px',
            });
            const icon = document.createElement('i');
            icon.className = 'fas fa-search';
            Object.assign(icon.style, { fontSize: '3rem', color: '#cbd5e1' });
            const span = document.createElement('span');
            span.setAttribute('data-tp-i18n', 'state_no_results');
            span.textContent = (window.tpT?.('state_no_results')) || 'Tidak ada berkas yang cocok dengan filter saat ini.';
            wrapper.appendChild(icon);
            wrapper.appendChild(span);
            this.gridContainer.appendChild(wrapper);
        } else if (!show && existing) {
            existing.remove();
        }
    }

    _renderPagination(totalPages, total) {
        if (!this.paginationContainer) return;
        this.paginationContainer.innerHTML = '';
        if (total === 0 || totalPages <= 1) return;

        const current = this.state.page;
        const start = (current - 1) * DocumentRepository.PAGE_SIZE + 1;
        const end = Math.min(current * DocumentRepository.PAGE_SIZE, total);

        const info = document.createElement('span');
        info.className = 'pagination-info';
        info.textContent = `${start}–${end} dari ${total} berkas`;
        this.paginationContainer.appendChild(info);

        const nav = document.createElement('nav');
        nav.className = 'pagination-nav';
        nav.setAttribute('aria-label', 'Navigasi halaman dokumen');

        const prev = document.createElement('button');
        prev.className = 'pagination-btn' + (current <= 1 ? ' disabled' : '');
        prev.disabled = current <= 1;
        prev.setAttribute('aria-label', 'Halaman sebelumnya');
        const prevIcon = document.createElement('i');
        prevIcon.className = 'fas fa-chevron-left';
        prev.appendChild(prevIcon);
        prev.addEventListener('click', () => {
            if (this.state.page > 1) { this.state.page--; this._applyFilters(); this._scrollToGrid(); }
        });
        nav.appendChild(prev);

        this._paginationRange(current, totalPages).forEach(p => {
            if (p === '...') {
                const el = document.createElement('span');
                el.className = 'pagination-ellipsis';
                el.setAttribute('aria-hidden', 'true');
                el.textContent = '…';
                nav.appendChild(el);
            } else {
                const btn = document.createElement('button');
                btn.className = 'pagination-btn pagination-number' + (p === current ? ' active' : '');
                btn.textContent = p;
                btn.setAttribute('aria-label', `Halaman ${p}`);
                if (p === current) btn.setAttribute('aria-current', 'page');
                btn.addEventListener('click', () => {
                    this.state.page = p; this._applyFilters(); this._scrollToGrid();
                });
                nav.appendChild(btn);
            }
        });

        const next = document.createElement('button');
        next.className = 'pagination-btn' + (current >= totalPages ? ' disabled' : '');
        next.disabled = current >= totalPages;
        next.setAttribute('aria-label', 'Halaman berikutnya');
        const nextIcon = document.createElement('i');
        nextIcon.className = 'fas fa-chevron-right';
        next.appendChild(nextIcon);
        next.addEventListener('click', () => {
            if (this.state.page < totalPages) { this.state.page++; this._applyFilters(); this._scrollToGrid(); }
        });
        nav.appendChild(next);

        this.paginationContainer.appendChild(nav);
    }

    // Returns page numbers and '...' ellipsis placeholders for the given range.
    _paginationRange(current, total) {
        if (total <= 7) return Array.from({ length: total }, (_, i) => i + 1);

        const pages = [1];
        const lo = Math.max(2, current - 1);
        const hi = Math.min(total - 1, current + 1);

        if (lo > 2) pages.push('...');
        for (let i = lo; i <= hi; i++) pages.push(i);
        if (hi < total - 1) pages.push('...');
        pages.push(total);

        return pages;
    }

    _scrollToGrid() {
        document.getElementById('repository')?.scrollIntoView({ behavior: 'smooth', block: 'start' });
    }

    _cardMatches(view) {
        const { filter, search } = this.state;
        const matchesCategory = filter === 'all' || view.category === filter;
        const matchesTitle = view.title.toLowerCase().includes(search);
        const matchesTags = search
            ? view.tags.some(t => t.toLowerCase().includes(search))
            : false;
        const matchesSearch = matchesTitle || matchesTags;
        return matchesCategory && matchesSearch && this._dateMatches(view.dateKey);
    }

    _dateMatches(dateKey) {
        const { startDate, endDate } = this.state;
        if (!dateKey) return !startDate && !endDate;
        const cardDate = new Date(dateKey);
        if (startDate && cardDate < new Date(startDate)) return false;
        if (endDate) {
            const end = new Date(endDate);
            end.setHours(23, 59, 59, 999);
            if (cardDate > end) return false;
        }
        return true;
    }

    _applySort() {
        const { sort } = this.state;
        this.cards.sort((a, b) => {
            if (sort === 'newest') return b.view.dateKey.localeCompare(a.view.dateKey);
            if (sort === 'oldest') return a.view.dateKey.localeCompare(b.view.dateKey);
            if (sort === 'az') return a.view.title.toLowerCase().localeCompare(b.view.title.toLowerCase());
            return 0;
        });
        this.cards.forEach(({ element }) => this.gridContainer.appendChild(element));
    }
}
