import { useEffect, useState, useRef, useCallback } from 'react';

/**
 * Accessibility utilities and hooks for WCAG 2.1 AA compliance
 */

// ==================== HOOKS ====================

/**
 * Detects if user prefers reduced motion
 */
export function usePrefersReducedMotion(): boolean {
    const [prefersReduced, setPrefersReduced] = useState(() => {
        if (typeof window === 'undefined') return false;
        return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    });

    useEffect(() => {
        const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
        const handler = (e: MediaQueryListEvent) => setPrefersReduced(e.matches);

        mediaQuery.addEventListener('change', handler);
        return () => mediaQuery.removeEventListener('change', handler);
    }, []);

    return prefersReduced;
}

/**
 * Detects if user prefers high contrast
 */
export function usePrefersHighContrast(): boolean {
    const [prefersHighContrast, setPrefersHighContrast] = useState(() => {
        if (typeof window === 'undefined') return false;
        return window.matchMedia('(prefers-contrast: more)').matches;
    });

    useEffect(() => {
        const mediaQuery = window.matchMedia('(prefers-contrast: more)');
        const handler = (e: MediaQueryListEvent) => setPrefersHighContrast(e.matches);

        mediaQuery.addEventListener('change', handler);
        return () => mediaQuery.removeEventListener('change', handler);
    }, []);

    return prefersHighContrast;
}

/**
 * Manage focus trap for modals/dialogs
 */
export function useFocusTrap(isActive: boolean) {
    const containerRef = useRef<HTMLDivElement>(null);
    const previousFocusRef = useRef<HTMLElement | null>(null);

    useEffect(() => {
        if (!isActive) return;

        // Store current focus
        previousFocusRef.current = document.activeElement as HTMLElement;

        const container = containerRef.current;
        if (!container) return;

        // Get focusable elements
        const focusableSelector = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
        const focusableElements = container.querySelectorAll<HTMLElement>(focusableSelector);
        const firstFocusable = focusableElements[0];
        const lastFocusable = focusableElements[focusableElements.length - 1];

        // Focus first element
        firstFocusable?.focus();

        const handleKeyDown = (e: KeyboardEvent) => {
            if (e.key !== 'Tab') return;

            if (e.shiftKey) {
                if (document.activeElement === firstFocusable) {
                    e.preventDefault();
                    lastFocusable?.focus();
                }
            } else {
                if (document.activeElement === lastFocusable) {
                    e.preventDefault();
                    firstFocusable?.focus();
                }
            }
        };

        container.addEventListener('keydown', handleKeyDown);

        return () => {
            container.removeEventListener('keydown', handleKeyDown);
            // Restore focus on unmount
            previousFocusRef.current?.focus();
        };
    }, [isActive]);

    return containerRef;
}

/**
 * Announce message to screen readers
 */
export function useAnnounce() {
    const announce = useCallback((message: string, priority: 'polite' | 'assertive' = 'polite') => {
        const el = document.createElement('div');
        el.setAttribute('role', 'status');
        el.setAttribute('aria-live', priority);
        el.setAttribute('aria-atomic', 'true');
        el.className = 'sr-only';
        el.textContent = message;

        document.body.appendChild(el);

        // Remove after announcement
        setTimeout(() => document.body.removeChild(el), 1000);
    }, []);

    return announce;
}

/**
 * Handle roving tabindex for arrow key navigation
 */
export function useRovingTabIndex<T extends HTMLElement>(itemCount: number) {
    const [activeIndex, setActiveIndex] = useState(0);
    const itemsRef = useRef<(T | null)[]>([]);

    const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
        let newIndex = activeIndex;

        switch (e.key) {
            case 'ArrowDown':
            case 'ArrowRight':
                e.preventDefault();
                newIndex = (activeIndex + 1) % itemCount;
                break;
            case 'ArrowUp':
            case 'ArrowLeft':
                e.preventDefault();
                newIndex = (activeIndex - 1 + itemCount) % itemCount;
                break;
            case 'Home':
                e.preventDefault();
                newIndex = 0;
                break;
            case 'End':
                e.preventDefault();
                newIndex = itemCount - 1;
                break;
            default:
                return;
        }

        setActiveIndex(newIndex);
        itemsRef.current[newIndex]?.focus();
    }, [activeIndex, itemCount]);

    const getItemProps = (index: number) => ({
        ref: (el: T | null) => { itemsRef.current[index] = el; },
        tabIndex: index === activeIndex ? 0 : -1,
        onKeyDown: handleKeyDown,
    });

    return { activeIndex, setActiveIndex, getItemProps };
}

// ==================== UTILITIES ====================

/**
 * Generate unique ID for ARIA relationships
 */
let idCounter = 0;
export function generateAriaId(prefix: string = 'aria'): string {
    return `${prefix}-${++idCounter}`;
}

/**
 * Check if color contrast meets WCAG standards
 * Returns ratio (4.5:1 for AA normal text, 3:1 for large text)
 */
export function getContrastRatio(foreground: string, background: string): number {
    const getLuminance = (hex: string): number => {
        const rgb = parseInt(hex.slice(1), 16);
        const r = ((rgb >> 16) & 0xff) / 255;
        const g = ((rgb >> 8) & 0xff) / 255;
        const b = (rgb & 0xff) / 255;

        const toLinear = (c: number) =>
            c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);

        return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);
    };

    const l1 = getLuminance(foreground);
    const l2 = getLuminance(background);
    const lighter = Math.max(l1, l2);
    const darker = Math.min(l1, l2);

    return (lighter + 0.05) / (darker + 0.05);
}

/**
 * Format number for screen readers
 */
export function formatNumberForSR(num: number, type: 'currency' | 'percent' | 'decimal' = 'decimal'): string {
    switch (type) {
        case 'currency':
            return `${num.toFixed(2)} dollars`;
        case 'percent':
            return `${num} percent`;
        default:
            return num.toLocaleString();
    }
}

// ==================== COMPONENTS ====================

/**
 * Screen reader only text
 */
export function VisuallyHidden({ children }: { children: React.ReactNode }) {
    return (
        <span className="sr-only">
            {children}
        </span>
    );
}

/**
 * Skip link for keyboard navigation
 */
export function SkipLink({ href, children }: { href: string; children: React.ReactNode }) {
    return (
        <a href={href} className="skip-to-main">
            {children}
        </a>
    );
}

/**
 * Live region for dynamic announcements
 */
export function LiveRegion({
    message,
    priority = 'polite'
}: {
    message: string;
    priority?: 'polite' | 'assertive'
}) {
    return (
        <div
            role="status"
            aria-live={priority}
            aria-atomic="true"
            className="sr-only"
        >
            {message}
        </div>
    );
}
