/**
 * Controller for credits dual-button UI (Watch Credits & Next Episode)
 */

import {
    VideoSegment,
    ChapterConfig
} from './types/ChapterTypes';

interface CreditsButtonCallbacks {
    onWatchCredits: (segment: VideoSegment) => void;
    onNextEpisode: (segment: VideoSegment, url: string) => void;
    onAutoRedirect: (segment: VideoSegment, url: string) => void;
    onButtonsShown: (segment: VideoSegment) => void;
    onButtonsHidden: (segment: VideoSegment, reason: string) => void;
}

export class CreditsButtonController {
    private buttonsContainer: HTMLElement | null = null;
    private watchCreditsButton: HTMLElement | null = null;
    private nextEpisodeButton: HTMLElement | null = null;
    private currentSegment: VideoSegment | null = null;
    private autoRedirectTimeout: NodeJS.Timeout | null = null;
    private countdownInterval: NodeJS.Timeout | null = null;
    private isVisible = false;
    private userWatchingCredits = false;

    // Default labels
    private readonly DEFAULT_WATCH_CREDITS_LABEL = 'Watch Credits';
    private readonly DEFAULT_NEXT_EPISODE_LABEL = 'Play Next';
    private readonly DEFAULT_AUTO_REDIRECT_DELAY = 10; // seconds

    constructor(
        private playerContainer: HTMLElement,
        private config: ChapterConfig,
        private callbacks: CreditsButtonCallbacks
    ) { }

    /**
     * Show credits buttons for a segment with next episode URL
     */
    public showCreditsButtons(segment: VideoSegment, currentTime: number): void {
        // Verify segment has nextEpisodeUrl
        if (!segment.nextEpisodeUrl) {
            return;
        }

        this.currentSegment = segment;
        this.userWatchingCredits = false;

        // Create buttons if they don't exist
        if (!this.buttonsContainer) {
            this.createCreditsButtons();
        }

        // Update button content
        this.updateButtonLabels(segment);

        // Show the buttons
        this.showButtons();

        // Start auto-redirect countdown
        const delay = segment.autoSkipDelay || this.DEFAULT_AUTO_REDIRECT_DELAY;
        this.startAutoRedirectCountdown(segment, delay);

        // Emit event
        this.callbacks.onButtonsShown(segment);
    }

    /**
     * Hide credits buttons
     */
    public hideCreditsButtons(reason: 'timeout' | 'segment-end' | 'user-action' | 'manual' = 'manual'): void {
        if (!this.buttonsContainer || !this.isVisible) {
            return;
        }

        // Emit event before cleanup
        if (this.currentSegment) {
            this.callbacks.onButtonsHidden(this.currentSegment, reason);
        }

        this.hideButtons();
        this.clearTimeouts();

        this.isVisible = false;
        this.currentSegment = null;
    }

    /**
     * Check if user is watching credits (clicked "Watch Credits")
     */
    public isUserWatchingCredits(): boolean {
        return this.userWatchingCredits;
    }

    /**
     * Get current segment
     */
    public getCurrentSegment(): VideoSegment | null {
        return this.currentSegment;
    }

    /**
     * Check if buttons are visible
     */
    public isButtonsVisible(): boolean {
        return this.isVisible;
    }

    /**
     * Destroy the credits button controller
     */
    public destroy(): void {
        this.clearTimeouts();
        if (this.buttonsContainer) {
            this.buttonsContainer.remove();
            this.buttonsContainer = null;
        }
        this.watchCreditsButton = null;
        this.nextEpisodeButton = null;
        this.currentSegment = null;
        this.isVisible = false;
        this.userWatchingCredits = false;
    }

    /**
     * Create the credits buttons DOM elements
     */
    private createCreditsButtons(): void {
        const segment = this.currentSegment;
        const style = segment?.creditsButtonStyle;
        const layout = style?.layout || 'vertical';
        const position = style?.position || 'bottom-right';

        // Create container
        this.buttonsContainer = document.createElement('div');
        this.buttonsContainer.className = 'uvf-credits-buttons';
        this.buttonsContainer.setAttribute('role', 'group');
        this.buttonsContainer.setAttribute('aria-label', 'Credits navigation');

        // Apply container styles based on layout and position
        const containerStyles: Partial<CSSStyleDeclaration> = {
            position: 'absolute',
            display: 'flex',
            flexDirection: layout === 'horizontal' ? 'row' : 'column',
            gap: '10px',
            zIndex: '1000',
            opacity: '0',
            transition: 'opacity 0.3s ease-in-out'
        };

        // Position the container
        this.applyContainerPosition(containerStyles, position);
        Object.assign(this.buttonsContainer.style, containerStyles);

        // Create "Watch Credits" button
        this.watchCreditsButton = document.createElement('button');
        this.watchCreditsButton.className = 'uvf-watch-credits-button';
        this.watchCreditsButton.setAttribute('type', 'button');
        this.watchCreditsButton.setAttribute('aria-label', 'Watch credits');

        // Add click handler for Watch Credits
        this.watchCreditsButton.addEventListener('click', () => this.handleWatchCreditsClick());

        // Create "Next Episode" button
        this.nextEpisodeButton = document.createElement('button');
        this.nextEpisodeButton.className = 'uvf-next-episode-button';
        this.nextEpisodeButton.setAttribute('type', 'button');
        this.nextEpisodeButton.setAttribute('aria-label', 'Play next episode');

        // Add click handler for Next Episode
        this.nextEpisodeButton.addEventListener('click', () => this.handleNextEpisodeClick());

        // Apply button styles with custom colors
        this.applyButtonStyles(this.watchCreditsButton, 'watch-credits', style);
        this.applyButtonStyles(this.nextEpisodeButton, 'next-episode', style);

        // Append buttons to container
        this.buttonsContainer.appendChild(this.watchCreditsButton);
        this.buttonsContainer.appendChild(this.nextEpisodeButton);

        // Append container to player
        this.playerContainer.appendChild(this.buttonsContainer);
    }

    /**
     * Apply position styles to container
     */
    private applyContainerPosition(styles: Partial<CSSStyleDeclaration>, position: string): void {
        switch (position) {
            case 'bottom-right':
                Object.assign(styles, { bottom: '100px', right: '30px' });
                break;
            case 'bottom-left':
                Object.assign(styles, { bottom: '100px', left: '30px' });
                break;
            case 'bottom-center':
                Object.assign(styles, { bottom: '100px', left: '50%', transform: 'translateX(-50%)' });
                break;
            case 'top-right':
                Object.assign(styles, { top: '30px', right: '30px' });
                break;
            case 'top-left':
                Object.assign(styles, { top: '30px', left: '30px' });
                break;
            case 'top-center':
                Object.assign(styles, { top: '30px', left: '50%', transform: 'translateX(-50%)' });
                break;
        }
    }

    /**
     * Apply styles to buttons
     */
    private applyButtonStyles(button: HTMLElement, type: 'watch-credits' | 'next-episode', customStyle?: any): void {
        const baseStyles: Partial<CSSStyleDeclaration> = {
            padding: '12px 24px',
            fontSize: '14px',
            fontWeight: '600',
            border: 'none',
            borderRadius: '6px',
            cursor: 'pointer',
            transition: 'all 0.2s ease-in-out',
            fontFamily: 'inherit',
            outline: 'none',
            minWidth: '180px',
            position: 'relative'
        };

        if (type === 'watch-credits') {
            Object.assign(baseStyles, {
                backgroundColor: customStyle?.watchCreditsBgColor || 'rgba(255, 255, 255, 0.15)',
                color: customStyle?.watchCreditsColor || '#ffffff',
                border: `2px solid ${customStyle?.watchCreditsBgColor ? 'transparent' : 'rgba(255, 255, 255, 0.3)'}`
            });
        } else {
            Object.assign(baseStyles, {
                backgroundColor: customStyle?.nextEpisodeBgColor || '#e50914',
                color: customStyle?.nextEpisodeColor || '#ffffff',
                boxShadow: '0 2px 8px rgba(229, 9, 20, 0.4)'
            });
        }

        Object.assign(button.style, baseStyles);

        // Add hover effect
        button.addEventListener('mouseenter', () => {
            if (type === 'watch-credits') {
                button.style.backgroundColor = customStyle?.watchCreditsBgColor
                    ? this.adjustBrightness(customStyle.watchCreditsBgColor, 20)
                    : 'rgba(255, 255, 255, 0.25)';
            } else {
                button.style.backgroundColor = customStyle?.nextEpisodeBgColor
                    ? this.adjustBrightness(customStyle.nextEpisodeBgColor, 20)
                    : '#f40612';
                button.style.transform = 'scale(1.03)';
            }
        });

        button.addEventListener('mouseleave', () => {
            if (type === 'watch-credits') {
                button.style.backgroundColor = customStyle?.watchCreditsBgColor || 'rgba(255, 255, 255, 0.15)';
            } else {
                button.style.backgroundColor = customStyle?.nextEpisodeBgColor || '#e50914';
                button.style.transform = 'scale(1)';
            }
        });
    }

    /**
     * Adjust color brightness for hover effects
     */
    private adjustBrightness(color: string, percent: number): string {
        // Simple brightness adjustment - works for hex and rgb
        const num = parseInt(color.replace('#', ''), 16);
        const amt = Math.round(2.55 * percent);
        const R = (num >> 16) + amt;
        const G = (num >> 8 & 0x00FF) + amt;
        const B = (num & 0x0000FF) + amt;
        return '#' + (0x1000000 + (R < 255 ? R < 1 ? 0 : R : 255) * 0x10000 +
            (G < 255 ? G < 1 ? 0 : G : 255) * 0x100 +
            (B < 255 ? B < 1 ? 0 : B : 255))
            .toString(16).slice(1);
    }

    /**
     * Update button labels based on segment configuration
     */
    private updateButtonLabels(segment: VideoSegment): void {
        if (!this.watchCreditsButton || !this.nextEpisodeButton) return;

        const watchLabel = segment.watchCreditsLabel || this.DEFAULT_WATCH_CREDITS_LABEL;
        const nextLabel = segment.nextEpisodeLabel || this.DEFAULT_NEXT_EPISODE_LABEL;

        this.watchCreditsButton.textContent = watchLabel;
        this.nextEpisodeButton.textContent = nextLabel;

        this.watchCreditsButton.setAttribute('aria-label', watchLabel);
        this.nextEpisodeButton.setAttribute('aria-label', nextLabel);
    }

    /**
     * Show buttons with animation
     */
    private showButtons(): void {
        if (!this.buttonsContainer) return;

        this.buttonsContainer.style.opacity = '1';
        this.isVisible = true;
    }

    /**
   * Hide buttons with animation
   */
    private hideButtons(): void {
        if (!this.buttonsContainer) return;

        // Remove from DOM instead of just hiding with opacity
        // This prevents accessibility tooltips from showing
        this.buttonsContainer.remove();
        this.buttonsContainer = null;
        this.watchCreditsButton = null;
        this.nextEpisodeButton = null;
    }

    /**
     * Handle "Watch Credits" button click
     */
    private handleWatchCreditsClick(): void {
        if (!this.currentSegment) return;

        this.userWatchingCredits = true;
        this.clearTimeouts();
        this.hideCreditsButtons('user-action');

        // Emit event
        this.callbacks.onWatchCredits(this.currentSegment);
    }

    /**
     * Handle "Next Episode" button click
     */
    private handleNextEpisodeClick(): void {
        if (!this.currentSegment || !this.currentSegment.nextEpisodeUrl) return;

        this.clearTimeouts();

        // Emit event
        this.callbacks.onNextEpisode(this.currentSegment, this.currentSegment.nextEpisodeUrl);

        // Redirect to next episode
        this.redirectToNextEpisode(this.currentSegment.nextEpisodeUrl);
    }

    /**
     * Start auto-redirect countdown
     */
    private startAutoRedirectCountdown(segment: VideoSegment, delay: number): void {
        if (!this.nextEpisodeButton || !segment.nextEpisodeUrl) return;

        let remainingTime = delay;
        const originalLabel = segment.nextEpisodeLabel || this.DEFAULT_NEXT_EPISODE_LABEL;

        // Update button text with countdown
        this.nextEpisodeButton.textContent = `${originalLabel} (${remainingTime})`;

        // Create countdown progress bar
        const progressBar = this.createProgressBar();
        this.nextEpisodeButton.appendChild(progressBar);

        // Update countdown every second
        this.countdownInterval = setInterval(() => {
            remainingTime -= 1;

            if (this.nextEpisodeButton) {
                this.nextEpisodeButton.textContent = `${originalLabel} (${remainingTime})`;
                this.nextEpisodeButton.appendChild(progressBar);

                // Update progress bar
                const progress = ((delay - remainingTime) / delay) * 100;
                progressBar.style.width = `${progress}%`;
            }

            if (remainingTime <= 0) {
                this.clearTimeouts();

                // Emit auto-redirect event
                this.callbacks.onAutoRedirect(segment, segment.nextEpisodeUrl!);

                // Redirect to next episode
                this.redirectToNextEpisode(segment.nextEpisodeUrl!);
            }
        }, 1000);

        // Set final timeout as backup
        this.autoRedirectTimeout = setTimeout(() => {
            if (segment.nextEpisodeUrl) {
                this.callbacks.onAutoRedirect(segment, segment.nextEpisodeUrl);
                this.redirectToNextEpisode(segment.nextEpisodeUrl);
            }
        }, delay * 1000);
    }

    /**
     * Create countdown progress bar element
     */
    private createProgressBar(): HTMLElement {
        const progressBar = document.createElement('div');
        progressBar.className = 'uvf-countdown-progress';

        Object.assign(progressBar.style, {
            position: 'absolute',
            bottom: '0',
            left: '0',
            height: '3px',
            backgroundColor: 'rgba(255, 255, 255, 0.9)',
            width: '0%',
            transition: 'width 1s linear',
            borderRadius: '6px'
        });

        return progressBar;
    }

    /**
     * Redirect to next episode URL
     */
    private redirectToNextEpisode(url: string): void {
        window.location.href = url;
    }

    /**
     * Clear all timeouts and intervals
     */
    private clearTimeouts(): void {
        if (this.autoRedirectTimeout) {
            clearTimeout(this.autoRedirectTimeout);
            this.autoRedirectTimeout = null;
        }

        if (this.countdownInterval) {
            clearInterval(this.countdownInterval);
            this.countdownInterval = null;
        }
    }
}
