/**
 * VMO Video Generation UI
 * Interface for generating videos with Sora and managing 360° product viewers
 * 
 * @package VMO_AI_Builder
 * @since 9.0.0
 */

(function() {
    'use strict';

    class VMOVideoGenerator {
        constructor() {
            this.activeJobs = new Map();
            this.pollInterval = 10000; // 10 seconds
            
            // Bind AJAX handlers
            this.nonce = typeof vmo_ajax !== 'undefined' ? vmo_ajax.nonce : '';
            this.ajaxUrl = typeof vmo_ajax !== 'undefined' ? (vmo_ajax.ajax_url || vmo_ajax.ajaxurl) : '/wp-admin/admin-ajax.php';
        }

        async postJobAction(action, payload = {}) {
            const formData = new FormData();
            formData.append('action', action);
            formData.append('security', this.nonce);

            Object.entries(payload).forEach(([key, value]) => {
                if (value === undefined || value === null) return;
                formData.append(key, typeof value === 'object' ? JSON.stringify(value) : value);
            });

            const response = await fetch(this.ajaxUrl, {
                method: 'POST',
                body: formData,
                credentials: 'same-origin'
            });

            const data = await response.json();
            if (!data.success) {
                throw new Error(data.data?.plain_language_error || data.data?.message || 'Media job request failed');
            }
            return data.data || {};
        }

        /**
         * Generate a video background for hero section
         */
        async generateHeroVideo(businessContext, options = {}) {
            const prompt = this.buildHeroPrompt(businessContext);
            return this.startVideoGeneration(prompt, {
                ...options,
                video_type: 'hero_background',
                model: options.model || 'sora-2-pro',
                seconds: options.seconds || '8',
                size: '1280x720'
            });
        }

        /**
         * Generate a product showcase video
         */
        async generateProductVideo(productName, productDescription, options = {}) {
            const prompt = this.buildProductPrompt(productName, productDescription);
            return this.startVideoGeneration(prompt, {
                ...options,
                video_type: 'product_showcase',
                model: options.model || 'sora-2-pro',
                seconds: options.seconds || '8',
                size: '1280x720'
            });
        }

        /**
         * Generate 360° spin video from a single product image
         */
        async generate360FromImage(imageUrl, productName, options = {}) {
            const prompt = `360-degree rotating product view of ${productName}. Smooth continuous rotation, clean studio lighting, neutral background, professional ecommerce loop.`;
            return this.startVideoGeneration(prompt, {
                ...options,
                source_url: imageUrl,
                product_name: productName,
                video_type: '360_spin',
                model: options.model || 'sora-2-pro',
                seconds: options.seconds || '8',
                size: options.size || '1280x720'
            });
        }

        /**
         * Create 360° spin viewer from multiple product images (no AI needed)
         */
        async create360FromImages(images, containerSelector, options = {}) {
            return new Promise((resolve, reject) => {
                const formData = new FormData();
                formData.append('action', 'vmo_create_spin_video_from_images');
                formData.append('security', this.nonce);
                
                images.forEach((img, i) => {
                    formData.append(`images[${i}]`, img);
                });

                fetch(this.ajaxUrl, {
                    method: 'POST',
                    body: formData,
                    credentials: 'same-origin'
                })
                .then(response => response.json())
                .then(data => {
                    if (data.success) {
                        // Initialize the 360 viewer
                        const container = document.querySelector(containerSelector);
                        if (container && window.VMO360SpinViewer) {
                            const viewer = new VMO360SpinViewer(container, {
                                frames: data.data.frames,
                                ...data.data.config,
                                ...options
                            });
                            resolve({ viewer, config: data.data });
                        } else {
                            resolve(data.data);
                        }
                    } else {
                        reject(new Error(data.data?.message || 'Failed to create spin viewer'));
                    }
                })
                .catch(reject);
            });
        }

        /**
         * Start video generation
         */
        async startVideoGeneration(prompt, options = {}) {
            const mediaType = 'video';
            const slotContext = {
                schema: 'vmo_video_generator_slot_v1',
                slot_id: options.slot_id || options.media_id || '',
                media_id: options.media_id || '',
                page_id: options.page_id || '',
                section_id: options.section_id || '',
                product_id: options.product_id || '',
                placement_role: options.video_type || 'custom_video',
                media_type: mediaType,
                source: options.source || 'video_generator_panel',
                label: options.product_name || options.title || ''
            };
            const request = {
                project_id: window.currentProjectId || window.vmoCurrentProjectId || options.project_id || 0,
                media_type: mediaType,
                replacement_type: 'ai_video',
                prompt,
                model: options.model || 'sora-2',
                seconds: options.seconds || '8',
                size: options.size || '1280x720',
                source_url: options.source_url || '',
                slot_context: JSON.stringify(slotContext)
            };

            await this.postJobAction('vmo_estimate_media_replacement_job', request);
            const createData = await this.postJobAction('vmo_create_media_replacement_job', request);
            const job = createData.job || {};
            this.activeJobs.set(job.id, {
                type: options.video_type || 'custom',
                prompt,
                title: options.title || 'VMO Video',
                attachmentId: job.attachment_id || 0,
                startTime: Date.now(),
                status: job.status || 'queued',
                progress: job.progress || 0
            });
            this.emitProgress(job.id, job.stage_label || job.status || 'queued', job.progress || 0);

            return this.waitForReplacementJob(job.id, options.video_type || 'custom');
        }

        async waitForReplacementJob(jobId, type) {
            let attempts = 0;
            let softNoticeShown = false;
            const softNoticeAttempts = 180;
            const slowPollInterval = Math.max(this.pollInterval, 15000);

            return new Promise((resolve, reject) => {
                const poll = async () => {
                    attempts += 1;
                    try {
                        const data = await this.postJobAction('vmo_get_media_replacement_job', { job_id: jobId });
                        const job = data.job || {};
                        this.emitProgress(jobId, job.stage_label || job.status || 'queued', job.progress || 0);

                        if (job.status === 'complete' && job.url) {
                            this.activeJobs.delete(jobId);
                            resolve({
                                videoId: jobId,
                                url: job.url,
                                attachmentId: job.attachment_id || 0,
                                type
                            });
                            return;
                        }

                        if (job.status === 'failed') {
                            this.activeJobs.delete(jobId);
                            reject(new Error(job.plain_language_error || job.error || 'Video generation failed'));
                            return;
                        }

                        if (attempts >= softNoticeAttempts) {
                            softNoticeShown = true;
                            this.emitProgress(
                                jobId,
                                'This generation is taking longer than usual, but the job is still active. VMO will continue processing it safely.',
                                Math.max(parseInt(job.progress || 0, 10) || 0, 60)
                            );
                        }

                        setTimeout(poll, softNoticeShown ? slowPollInterval : this.pollInterval);
                    } catch (error) {
                        const message = String(error?.message || '');
                        if (/not found|unauthorized|not logged in/i.test(message)) {
                            this.activeJobs.delete(jobId);
                            reject(error);
                            return;
                        }
                        softNoticeShown = softNoticeShown || attempts >= softNoticeAttempts;
                        if (softNoticeShown) {
                            this.emitProgress(
                                jobId,
                                'VMO is still checking this media job. Generation continues safely in the background.',
                                60
                            );
                        }
                        setTimeout(poll, softNoticeShown ? slowPollInterval : this.pollInterval);
                    }
                };

                setTimeout(poll, 1500);
            });
        }

        /**
         * Track a video generation job
         */
        trackJob(videoId, jobInfo) {
            this.activeJobs.set(videoId, {
                ...jobInfo,
                startTime: Date.now(),
                status: 'queued'
            });

            this.pollJobStatus(videoId);
        }

        /**
         * Poll for job status
         */
        async pollJobStatus(videoId) {
            const job = this.activeJobs.get(videoId);
            if (!job) return;

            try {
                const data = await this.postJobAction('vmo_get_media_replacement_job', { job_id: videoId });
                const replacementJob = data.job || {};
                const status = replacementJob.status;
                const progress = replacementJob.progress || 0;

                // Update job status
                job.status = status;
                job.progress = progress;

                // Emit progress event
                this.emitProgress(videoId, status, progress);

                if (status === 'complete') {
                    job.onComplete({
                        videoId,
                        url: replacementJob.url,
                        attachmentId: replacementJob.attachment_id || 0,
                        type: job.type
                    });
                    this.activeJobs.delete(videoId);
                } else if (status === 'failed') {
                    job.onError(new Error(replacementJob.plain_language_error || replacementJob.error || 'Video generation failed'));
                    this.activeJobs.delete(videoId);
                } else {
                    // Continue polling
                    setTimeout(() => this.pollJobStatus(videoId), this.pollInterval);
                }
            } catch (error) {
                job.onError(error);
                this.activeJobs.delete(videoId);
            }
        }

        /**
         * Download completed video
         */
        async downloadCompletedVideo(videoId, job) {
            this.pollJobStatus(videoId);
        }

        /**
         * Emit progress event
         */
        emitProgress(videoId, status, progress) {
            const event = new CustomEvent('vmo:video:progress', {
                detail: { videoId, status, progress }
            });
            document.dispatchEvent(event);
        }

        /**
         * Build hero video prompt
         */
        buildHeroPrompt(context) {
            const industry = context.industry || 'business';
            const personality = context.brand_personality || 'modern and professional';
            const colors = context.colors || '';
            
            let prompt = `Cinematic hero background video for a ${industry} website. `;
            prompt += `Brand style: ${personality}. `;
            prompt += `Smooth, subtle motion perfect for a website hero section. `;
            
            if (colors) {
                prompt += `Color palette hints: ${colors}. `;
            }
            
            prompt += `No text, no people's faces, no logos. `;
            prompt += `Elegant lighting, shallow depth of field, professional color grading. `;
            prompt += `Ambient movement that doesn't distract from overlaid text.`;
            
            return prompt;
        }

        /**
         * Build product video prompt
         */
        buildProductPrompt(name, description) {
            let prompt = `Professional product showcase video for: ${name}. `;
            
            if (description) {
                prompt += `Product: ${description}. `;
            }
            
            prompt += `Elegant presentation on a clean, minimalist background. `;
            prompt += `Smooth camera movement around the product. `;
            prompt += `Soft studio lighting, subtle shadows, premium feel. `;
            prompt += `No text, no watermarks. `;
            prompt += `E-commerce quality, high-end product photography style in motion.`;
            
            return prompt;
        }

        /**
         * Get token cost estimate for video
         */
        getTokenCost(model = 'sora-2', seconds = '8') {
            const costs = {
                'sora-2': { '4': 2000, '8': 3500, '12': 5000 },
                'sora-2-pro': { '4': 4000, '8': 7000, '12': 10000 }
            };
            return costs[model]?.[seconds] || 3500;
        }

        /**
         * Check if product type benefits from 360° view
         */
        productNeeds360View(businessType, productType = '') {
            const physicalProducts = [
                'shoe', 'footwear', 'sneaker',
                'cosmetic', 'makeup', 'beauty',
                'jewelry', 'watch',
                'bag', 'handbag', 'purse',
                'furniture', 'chair', 'table',
                'electronics', 'phone', 'laptop',
                'clothing', 'apparel', 'fashion',
                'art', 'sculpture', 'collectible',
                'toy', 'appliance', 'cookware',
                'sports', 'equipment', 'gear',
                'ecommerce', 'shop', 'store',
                'dropshipping', 'retail'
            ];

            const serviceBusinesses = [
                'videographer', 'photographer',
                'consultant', 'lawyer', 'accountant',
                'doctor', 'dentist', 'therapist',
                'coach', 'agency', 'marketing',
                'cleaning', 'lawn', 'handyman',
                'restaurant', 'cafe', 'catering',
                'gym', 'fitness', 'yoga',
                'real estate', 'insurance',
                'education', 'tutoring',
                'non-profit', 'church'
            ];

            const checkText = (businessType + ' ' + productType).toLowerCase();

            // Services don't need 360°
            for (const service of serviceBusinesses) {
                if (checkText.includes(service)) return false;
            }

            // Physical products benefit from 360°
            for (const product of physicalProducts) {
                if (checkText.includes(product)) return true;
            }

            // Default based on keywords
            return checkText.includes('product') || checkText.includes('sell');
        }
    }

    // Create and expose instance
    window.VMOVideoGenerator = new VMOVideoGenerator();

    // Helper function for easy access
    window.vmoGenerateVideo = async function(type, context, options = {}) {
        const generator = window.VMOVideoGenerator;
        
        switch (type) {
            case 'hero':
                return generator.generateHeroVideo(context, options);
            case 'product':
                return generator.generateProductVideo(context.name, context.description, options);
            case '360-image':
                return generator.generate360FromImage(context.imageUrl, context.name, options);
            case '360-images':
                return generator.create360FromImages(context.images, context.container, options);
            default:
                return generator.startVideoGeneration(context.prompt, options);
        }
    };

})();
