type VideoWithWebkitFs = HTMLVideoElement & {
    webkitEnterFullscreen?: () => void
    webkitExitFullscreen?: () => void
    webkitDisplayingFullscreen?: boolean
    webkitSupportsFullscreen?: boolean
}

type ElementWithWebkitFs = HTMLElement & {
    webkitRequestFullscreen?: () => Promise<void> | void
}

type DocumentWithWebkitFs = Document & {
    webkitFullscreenElement?: Element | null
    webkitExitFullscreen?: () => Promise<void> | void
}

function isLikelyMobileViewport(): boolean {
    if (typeof window === 'undefined' || typeof navigator === 'undefined') return false
    if (/Android|iPhone|iPad|iPod|Mobile|webOS|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
        return true
    }
    return navigator.maxTouchPoints > 1 && window.matchMedia('(max-width: 1024px)').matches
}

/** 是否應優先使用 video 元素全螢幕（iOS Safari、多數行動瀏覽器等） */
export function prefersVideoElementFullscreen(video: HTMLVideoElement | null): boolean {
    if (!video) return false
    const v = video as VideoWithWebkitFs
    if (v.webkitSupportsFullscreen === false) return false
    if (typeof v.webkitEnterFullscreen === 'function') return true
    if (isLikelyMobileViewport()) return true
    if (typeof document !== 'undefined' && !document.fullscreenEnabled) return true
    return false
}

export function isVideoFullscreenActive(
    container: HTMLElement | null,
    video: HTMLVideoElement | null
): boolean {
    if (typeof document === 'undefined') return false
    const doc = document as DocumentWithWebkitFs
    const fsEl = document.fullscreenElement ?? doc.webkitFullscreenElement ?? null
    if (fsEl && (fsEl === container || fsEl === video)) return true
    const v = video as VideoWithWebkitFs | null
    return Boolean(v?.webkitDisplayingFullscreen)
}

export async function requestVideoFullscreen(
    container: HTMLElement,
    video: HTMLVideoElement | null
): Promise<boolean> {
    if (typeof document === 'undefined') return false

    const v = video as VideoWithWebkitFs | null

    if (v && prefersVideoElementFullscreen(v)) {
        try {
            if (typeof v.webkitEnterFullscreen === 'function') {
                v.webkitEnterFullscreen()
                return true
            }
        } catch {
            // fall through
        }
        try {
            if (video?.requestFullscreen) {
                // 勿 await，避免脫離使用者手勢鏈（行動瀏覽器常因此靜默失敗）
                void video.requestFullscreen()
                return true
            }
        } catch {
            // fall through
        }
    }

    try {
        if (container.requestFullscreen) {
            await container.requestFullscreen()
            return true
        }
    } catch {
        // fall through
    }

    try {
        const c = container as ElementWithWebkitFs
        if (c.webkitRequestFullscreen) {
            await c.webkitRequestFullscreen()
            return true
        }
    } catch {
        // fall through
    }

    if (v) {
        try {
            if (typeof v.webkitEnterFullscreen === 'function') {
                v.webkitEnterFullscreen()
                return true
            }
        } catch {
            // ignore
        }
        try {
            if (video?.requestFullscreen) {
                await video.requestFullscreen()
                return true
            }
        } catch {
            // ignore
        }
    }

    return false
}

export async function exitVideoFullscreen(video: HTMLVideoElement | null): Promise<void> {
    if (typeof document === 'undefined') return

    const doc = document as DocumentWithWebkitFs
    const v = video as VideoWithWebkitFs | null

    if (v?.webkitDisplayingFullscreen && typeof v.webkitExitFullscreen === 'function') {
        try {
            v.webkitExitFullscreen()
            return
        } catch {
            // fall through
        }
    }

    if (document.fullscreenElement) {
        try {
            await document.exitFullscreen()
            return
        } catch {
            // fall through
        }
    }

    if (doc.webkitFullscreenElement && doc.webkitExitFullscreen) {
        try {
            await doc.webkitExitFullscreen()
        } catch {
            // ignore
        }
    }
}

export const FULLSCREEN_CHANGE_EVENTS = [
    'fullscreenchange',
    'webkitfullscreenchange',
] as const

export const VIDEO_WEBKIT_FS_EVENTS = ['webkitbeginfullscreen', 'webkitendfullscreen'] as const
