/**
 * Alpine Component: Videos Page
 */
import {
    requestJson,
    getCsrfToken,
    escapeHtml,
    formatDate,
    buildSocialLinksHtml,
    buildVideoProgressHtml,
    normalizeVideoStatusValue,
} from '../helpers';


function getExpectedVideoCount(row) {
    const rawColumnValue = row?.number_of_videos ?? row?.numberOfVideos ?? 0;
    const parsedColumn = Number.parseInt(String(rawColumnValue), 10);
    return Number.isFinite(parsedColumn) ? Math.max(0, parsedColumn) : 0;
}

function buildVideoListForDisplay(row) {
    return Array.isArray(row?.video_links)
        ? row.video_links.map((video) => ({
            ...video,
            status: normalizeVideoStatusValue(video?.status),
            url: String(video?.url || '').trim(),
        }))
        : [];
}

function getDeadlineLabelClient(row) {
    const expected = getExpectedVideoCount(row);
    const links = Array.isArray(row.video_links) ? row.video_links : [];
    const published = links.filter((v) => normalizeVideoStatusValue(v.status) === 'published').length;
    const missing = Math.max(0, expected - published);

    if (!row.air_date) return { status: 'no_deadline' };

    const deadline = new Date(row.air_date);
    if (Number.isNaN(deadline.getTime())) return { status: 'no_deadline' };

    if (missing <= 0) {
        return { status: 'completed', days: 0, missing: 0 };
    }

    const now = new Date();
    const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
    const due = new Date(deadline.getFullYear(), deadline.getMonth(), deadline.getDate());
    const msPerDay = 24 * 60 * 60 * 1000;
    const diff = Math.ceil((due - today) / msPerDay);

    if (diff < 0) return { status: 'late', days: diff, missing };
    if (diff === 0) return { status: 'today', days: 0, missing };
    if (diff >= 1 && diff <= 7) return { status: 'soon', days: diff, missing };
    return { status: 'daysleft', days: diff, missing };
}

function deadlineBadgeHtml(obj) {
    const status = typeof obj === 'string' ? obj : (obj?.status || 'no_deadline');
    const missing = Number.isFinite(obj?.missing) ? obj.missing : 0;
    const days = Number.isFinite(obj?.days) ? obj.days : null;

    let text = 'Chưa có deadline';
    let cls = 'deadline-badge--no_deadline';

    switch (status) {
        case 'completed':
            text = '✅ Hoàn thành';
            cls = 'deadline-badge--completed';
            break;
        case 'late':
            text = `⛔ Quá hạn - Thiếu ${missing} video`;
            cls = 'deadline-badge--late';
            break;
        case 'today':
            text = `🚨 Hôm nay - Thiếu ${missing} video`;
            cls = 'deadline-badge--today';
            break;
        case 'soon':
            text = `⏰ Còn ${days} ngày - Thiếu ${missing} video`;
            cls = 'deadline-badge--soon';
            break;
        case 'daysleft':
            text = `🔄 Còn ${days} ngày`;
            cls = 'deadline-badge--daysleft';
            break;
    }

    return `<span class="deadline-badge ${cls}">${escapeHtml(text)}</span>`;
}


export function registerVideosPage(Alpine) {
    Alpine.data('videosPage', () => ({
        campaigns: [],
        users: [],
        campaignKocs: [],
        filteredRows: [],
        metrics: {
            total_kocs: 0,
            pending: 0,
            published: 0,
            missing: 0,
        },
        filterCampaign: '',
        filterStatus: '',
        filterAssignedTo: '',
        filterDeadline: '',
        page: 1,
        pageSize: 10,
        expandedSections: {},
        expandedKocs: {},
        editingVideoId: null,
        isSavingVideo: false,
        editingRowId: null,
        editingDateField: null,
        editFormUrl: '',
        editFormSparkAds: '',
        editFormStatus: 'pending',
        deletingVideoRow: null,
        deletingVideoData: null,
        loading: false,
        loadError: '',

        get totalCampaignPages() {
            const count = this.matchingCampaigns.length;
            return Math.max(1, Math.ceil(count / this.pageSize));
        },

        get matchingCampaigns() {
            return this.campaigns.filter((c) =>
                this.filteredRows.some((r) => String(r.campaign_id) === String(c.id))
            );
        },

        get paginatedCampaigns() {
            const all = this.matchingCampaigns;
            const start = (this.page - 1) * this.pageSize;
            return all.slice(start, start + this.pageSize);
        },

        get paginationStart() {
            const total = this.matchingCampaigns.length;
            return total === 0 ? 0 : (this.page - 1) * this.pageSize + 1;
        },

        get paginationEnd() {
            return Math.min(this.page * this.pageSize, this.matchingCampaigns.length);
        },

        get visiblePages() {
            const pages = [];
            const total = this.totalCampaignPages;
            const start = Math.max(1, this.page - 2);
            const end = Math.min(total, this.page + 2);
            for (let i = start; i <= end; i++) pages.push(i);
            return pages;
        },

        init() {
            window.executeDeleteVideo = () => this.executeDeleteVideo();
            this.loadUsers();
            this.load();
        },

        async load() {
            this.loading = true;
            this.loadError = '';
            try {
                const [campaigns, metrics] = await Promise.all([
                    requestJson('/videos/campaigns'),
                    requestJson('/videos/metrics'),
                ]);

                this.campaigns = Array.isArray(campaigns) ? campaigns : [];
                this.metrics = metrics || this.metrics;
                this.campaignKocs = await this.fetchAllCampaignKocs();
                this.filteredRows = this.campaignKocs.slice();
                this.page = 1;
            } catch (e) {
                this.loadError = 'Lỗi tải dữ liệu';
                showError('Lỗi', 'Không thể tải dữ liệu video');
            } finally {
                this.loading = false;
            }
        },

        async loadUsers() {
            try {
                const users = await requestJson('/videos/users');
                this.users = Array.isArray(users) ? users : [];
            } catch (e) {
                this.users = [];
            }
        },

        async fetchAllCampaignKocs() {
            const chunkSize = 500;
            let skip = 0;
            const allRows = [];

            while (true) {
                const chunk = await requestJson(`/videos/data?skip=${skip}&limit=${chunkSize}`);
                if (!Array.isArray(chunk) || chunk.length === 0) break;
                allRows.push(...chunk);
                if (chunk.length < chunkSize) break;
                skip += chunkSize;
            }

            return allRows;
        },

        applyFilters() {
            this.filteredRows = this.campaignKocs.filter((row) => {
                if (this.filterCampaign && String(row.campaign_id) !== String(this.filterCampaign)) {
                    return false;
                }

                if (this.filterStatus) {
                    const links = Array.isArray(row.video_links) ? row.video_links : [];
                    const statuses = links.map((v) => normalizeVideoStatusValue(v.status));
                    const expected = getExpectedVideoCount(row);

                    if (this.filterStatus === 'Chưa lên video') {
                        if (expected <= 0) return false;
                        const publishedCount = statuses.filter((s) => s === 'published').length;
                        if (publishedCount >= expected) return false;
                    } else if (this.filterStatus === 'Đã đăng video') {
                        const publishedCount = statuses.filter((s) => s === 'published').length;
                        if (publishedCount <= 0) return false;
                    }
                }

                if (this.filterAssignedTo) {
                    const ownerId = row?.owner?.id || '';
                    if (String(ownerId) !== String(this.filterAssignedTo)) return false;
                }

                if (this.filterDeadline) {
                    const obj = getDeadlineLabelClient(row);
                    if (this.filterDeadline === 'empty' && obj.status !== 'no_deadline') return false;
                    if (this.filterDeadline === 'late' && obj.status !== 'late') return false;
                    if (this.filterDeadline === 'done' && obj.status !== 'completed') return false;
                    if (this.filterDeadline === 'upcoming' && obj.status !== 'today' && obj.status !== 'soon') return false;
                    if (this.filterDeadline === 'daysleft' && obj.status !== 'daysleft') return false;
                }

                return true;
            });

            this.page = 1;
        },

        clearFilters() {
            this.filterCampaign = '';
            this.filterStatus = '';
            this.filterAssignedTo = '';
            this.filterDeadline = '';
            this.applyFilters();
        },

        setFilterStatus(status) {
            this.filterCampaign = '';
            this.filterStatus = status;
            this.filterAssignedTo = '';
            this.filterDeadline = '';
            this.applyFilters();
        },

        toggleCampaignExpand(campaignId) {
            this.expandedSections[campaignId] = !this.expandedSections[campaignId];
        },

        isCampaignExpanded(campaignId) {
            return !!this.expandedSections[campaignId];
        },

        toggleKocExpand(kocId) {
            this.expandedKocs[kocId] = !this.expandedKocs[kocId];
        },

        isKocExpanded(kocId) {
            return !!this.expandedKocs[kocId];
        },

        rowsForCampaign(campaignId) {
            return this.filteredRows.filter((r) => String(r.campaign_id) === String(campaignId));
        },

        campaignHeaderStats(rows) {
            const counts = { published: 0, pending: 0 };
            let totalExpected = 0;
            rows.forEach((r) => {
                totalExpected += r.number_of_videos || 0;
                (r.video_links || []).forEach((v) => {
                    const status = normalizeVideoStatusValue(v.status);
                    if (status === 'published') counts.published++;
                });
            });
            counts.pending = Math.max(0, totalExpected - counts.published);
            return counts;
        },

        totalVideosForRows(rows) {
            return rows.reduce((sum, r) => sum + getExpectedVideoCount(r), 0);
        },

        getKocName(row) {
            return row?.koc?.creator_name || row?.creator_name || '—';
        },

        getProductName(row) {
            const campaign = this.campaigns.find((c) => String(c.id) === String(row.campaign_id));
            return campaign?.product_name || '—';
        },

        getOwnerName(row) {
            return row?.owner?.display_name || row?.owner_name || '—';
        },

        formatRowDate(value) {
            return formatDate(value) === '-' ? '—' : formatDate(value);
        },

        buildVideoList(row) {
            return buildVideoListForDisplay(row);
        },

        progressCellHtml(row) {
            return buildVideoProgressHtml(this.buildVideoList(row), {
                expectedCount: row.number_of_videos || 0,
            });
        },

        deadlineCellHtml(row) {
            return deadlineBadgeHtml(getDeadlineLabelClient(row));
        },

        socialLinksHtml(row) {
            const koc = row?.koc;
            const data = koc || row || {};
            let html = buildSocialLinksHtml(data);
            if (html === '-' && koc) {
                html = buildSocialLinksHtml(row);
            }
            if (html === '-') {
                return '<span class="videos-koc-cell--empty">—</span>';
            }
            return html;
        },

        startEditingVideo(video) {
            this.editingVideoId = String(video.id);
            this.editFormUrl = video.url || '';
            this.editFormSparkAds = video.spark_ads || '';
            this.editFormStatus = normalizeVideoStatusValue(video.status);
        },

        saveEditingVideo: window.withSubmitGuard('videos_save', async function (video) {
            if (!this.editingVideoId) return;
            const id = this.editingVideoId;
            const payload = {
                url: String(this.editFormUrl || '').trim(),
                spark_ads: String(this.editFormSparkAds || '').trim(),
            };
            try {
                await requestJson(`/videos/${id}`, {
                    method: 'PUT',
                    body: JSON.stringify(payload),
                });
                const applyUpdate = (row) => {
                    const links = row.video_links || [];
                    if (!links.some((v) => String(v.id) === String(id))) return row;
                    return {
                        ...row,
                        video_links: links.map((v) =>
                            String(v.id) === String(id)
                                ? { ...v, url: payload.url, status: payload.status, spark_ads: payload.spark_ads }
                                : v
                        ),
                    };
                };
                this.campaignKocs = this.campaignKocs.map(applyUpdate);
                this.filteredRows = this.filteredRows.map(applyUpdate);
                this.editingVideoId = null;
                showSuccess('Thành công', 'Đã cập nhật video');
            } catch (err) {
                if (err.errors && err.errors.url) {
                    showError('Lỗi', err.errors.url[0] || 'URL video đã tồn tại trong booking này');
                } else if (err.message) {
                    showError('Lỗi', err.message);
                } else {
                    showError('Lỗi', 'Không lưu được thay đổi video. Vui lòng thử lại.');
                }
            } finally {
                this.isSavingVideo = false;
            }
        }),

        cancelEditingVideo() {
            this.editingVideoId = null;
        },

        async copySparkAds(value, event) {
            event?.stopPropagation();
            try {
                await navigator.clipboard.writeText(value);
                showInfo('Đã copy', 'Spark Ads đã được sao chép');
            } catch (err) {
                showError('Lỗi', 'Không thể sao chép');
            }
        },

        startEditDate(rowId, field) {
            this.editingRowId = rowId;
            this.editingDateField = field;
        },

        async saveEditDate(row, field, event) {
            const value = event.target.value || null;
            row[field] = value;
            this.cancelEditDate();
            try {
                const resp = await fetch('/bookings/' + row.id, {
                    method: 'PUT',
                    headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-TOKEN': getCsrfToken() },
                    body: JSON.stringify({ [field]: value }),
                });
                if (!resp.ok) throw new Error('Status ' + resp.status);
                const label = field === 'send_date' ? 'ngày nhận SP' : 'ngày chốt air vid';
                showSuccess('Thành công', 'Đã cập nhật ' + label);
            } catch (e) {
                showError('Lỗi', 'Không thể cập nhật: ' + (e.message || e));
                this.load();
            }
        },

        cancelEditDate() {
            this.editingRowId = null;
            this.editingDateField = null;
        },

        existingVideoCount(row) {
            const links = Array.isArray(row?.video_links) ? row.video_links : [];
            return links.length;
        },

        canAddVideoRow(row) {
            return this.existingVideoCount(row) < (row.number_of_videos || 0);
        },

        async addVideoRow(row) {
            if (!this.canAddVideoRow(row)) return;
            const bookingId = row.id;
            try {
                const data = await requestJson('/videos/add-row', {
                    method: 'POST',
                    body: JSON.stringify({ booking_id: bookingId }),
                });
                const applyAdd = (r) => {
                    if (String(r.id) !== String(bookingId)) return r;
                    const newVideo = { ...data, isPlaceholder: false };
                    return { ...r, video_links: [...(r.video_links || []), newVideo] };
                };
                this.campaignKocs = this.campaignKocs.map(applyAdd);
                this.filteredRows = this.filteredRows.map(applyAdd);
                showSuccess('Thành công', 'Đã thêm hàng video mới');
            } catch (err) {
                showError('Lỗi', 'Không thể thêm hàng video. Vui lòng thử lại.');
            }
        },

        confirmDeleteVideo(row, video) {
            this.deletingVideoRow = row;
            this.deletingVideoData = video;
            modalOpen('deleteVideoConfirmModal');
        },

        async executeDeleteVideo() {
            const row = this.deletingVideoRow;
            const video = this.deletingVideoData;
            if (!row || !video) return;
            this.deletingVideoRow = null;
            this.deletingVideoData = null;
            const videoId = video.id;
            try {
                await requestJson(`/videos/${videoId}`, { method: 'DELETE' });
                const applyDelete = (r) => {
                    if (String(r.id) !== String(row.id)) return r;
                    return { ...r, video_links: (r.video_links || []).filter((v) => String(v.id) !== String(videoId)) };
                };
                this.campaignKocs = this.campaignKocs.map(applyDelete);
                this.filteredRows = this.filteredRows.map(applyDelete);
                showSuccess('Thành công', 'Đã xóa video');
            } catch (err) {
                showError('Lỗi', 'Không thể xóa video. Vui lòng thử lại.');
            } finally {
                modalClose('deleteVideoConfirmModal');
            }
        },

        goToPage(p) {
            this.page = Math.max(1, Math.min(p || 1, this.totalCampaignPages));
        },


        prevPage() {
            this.goToPage(this.page - 1);
        },

        nextPage() {
            this.goToPage(this.page + 1);
        },

        onPageSizeChange(size) {
            this.pageSize = parseInt(size, 10) || 10;
            this.page = 1;
        },
    }));
}
