package com.horrortv.app.domain.usecase

import android.util.Log
import com.horrortv.app.domain.model.VideoSource
import com.horrortv.app.domain.model.VideoType
import com.horrortv.app.domain.model.SubtitleTrack
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.jsoup.Jsoup
import java.net.HttpURLConnection
import java.net.URL

class VideoExtractor {
    
    companion object {
        private const val TAG = "VideoExtractor"
        private const val PLAYIMDB_BASE = "https://playimdb.com/title/"
        private const val STREAMIMDB_BASE = "https://streamimdb.me/embed/"
        private const val TIMEOUT_MS = 15000
    }
    
    suspend fun extractVideoSource(imdbId: String): Result<VideoSource> = withContext(Dispatchers.IO) {
        try {
            Log.d(TAG, "Extracting video for: $imdbId")
            
            val embedUrl = "$STREAMIMDB_BASE$imdbId"
            Log.d(TAG, "Fetching embed: $embedUrl")
            
            val html = fetchHtml(embedUrl)
            Log.d(TAG, "HTML length: ${html.length}")
            Log.d(TAG, "HTML snippet (first 2000 chars): ${html.take(2000)}")
            
            var doc = Jsoup.parse(html)
            
            val iframeUrl = doc.selectFirst("iframe")?.attr("src")
            if (iframeUrl != null && iframeUrl.isNotEmpty()) {
                val fullIframeUrl = if (iframeUrl.startsWith("//")) {
                    "https:$iframeUrl"
                } else {
                    iframeUrl
                }
                Log.d(TAG, "Found iframe redirect: $fullIframeUrl")
                try {
                    val iframeHtml = fetchHtml(fullIframeUrl)
                    Log.d(TAG, "Iframe HTML length: ${iframeHtml.length}")
                    Log.d(TAG, "IFRAME FULL HTML START =====")
                    Log.d(TAG, iframeHtml)
                    Log.d(TAG, "IFRAME FULL HTML END =====")
                    
                    val prorcpPattern = Regex("['\"]?src['\"]?\\s*:\\s*['\"]([^'\"]+/prorcp/[^'\"]+)['\"]")
                    val prorcpMatch = prorcpPattern.find(iframeHtml)
                    if (prorcpMatch != null) {
                        val innerUrl = prorcpMatch.groupValues[1]
                        val fullInnerUrl = if (innerUrl.startsWith("/")) {
                            "https://cloudnestra.com$innerUrl"
                        } else if (innerUrl.startsWith("//")) {
                            "https:$innerUrl"
                        } else {
                            innerUrl
                        }
                        Log.d(TAG, "Found prorcp URL: $fullInnerUrl")
                        try {
                            val innerHtml = fetchHtml(fullInnerUrl)
                            Log.d(TAG, "Prorcp HTML length: ${innerHtml.length}")
                            Log.d(TAG, "Prorcp FULL HTML: $innerHtml")
                            doc = Jsoup.parse(innerHtml)
                        } catch (e: Exception) {
                            Log.w(TAG, "Failed prorcp fetch: ${e.message}")
                        }
                    } else {
                        Log.d(TAG, "No prorcp pattern found, searching for /prorcp/ directly")
                        val directPattern = Regex("/prorcp/[A-Za-z0-9+/=]+")
                        val directMatch = directPattern.find(iframeHtml)
                        if (directMatch != null) {
                            val innerUrl = directMatch.value
                            val fullInnerUrl = "https://cloudnestra.com$innerUrl"
                            Log.d(TAG, "Found prorcp direct: $fullInnerUrl")
                            try {
                                val innerHtml = fetchHtml(fullInnerUrl)
                                Log.d(TAG, "Prorcp direct HTML length: ${innerHtml.length}")
                                Log.d(TAG, "Prorcp direct FULL HTML: $innerHtml")
                                doc = Jsoup.parse(innerHtml)
                            } catch (e: Exception) {
                                Log.w(TAG, "Failed prorcp direct fetch: ${e.message}")
                            }
                        }
                    }
                } catch (e: Exception) {
                    Log.w(TAG, "Failed to fetch iframe: ${e.message}")
                }
            }
            
            val videoUrl = extractVideoUrl(doc)
            if (videoUrl == null) {
                Log.w(TAG, "No video URL found in HTML")
                return@withContext Result.failure(VideoExtractionException("No video URL found"))
            }
            
            Log.d(TAG, "Video URL found: $videoUrl")
            
            val subtitles = extractSubtitles(doc)
            Log.d(TAG, "Subtitles found: ${subtitles.size}")
            
            val knownDomains = listOf(
                "neonhorizonworkshops.com",
                "wanderlynest.com",
                "orchidpixelgardens.com",
                "cloudnestra.com"
            )
            
            val finalVideoUrl = if (videoUrl.contains("{v")) {
                val basePattern = Regex("https://tmstr3\\.\\{v\\d+\\}/(.+)")
                val pathMatch = basePattern.find(videoUrl)
                if (pathMatch != null) {
                    val path = pathMatch.groupValues[1]
                    val testDomain = knownDomains.first()
                    val constructedUrl = "https://tmstr1.$testDomain/$path"
                    Log.d(TAG, "Constructed URL from known domain: $constructedUrl")
                    constructedUrl
                } else {
                    videoUrl.replace(Regex("\\{v\\d+\\}"), knownDomains.first())
                }
            } else {
                videoUrl
            }
            
            Log.d(TAG, "Final video URL: $finalVideoUrl")
            
            val videoType = determineVideoType(finalVideoUrl)
            Log.d(TAG, "Video type: $videoType")
            
            Result.success(
                VideoSource(
                    videoUrl = finalVideoUrl,
                    videoType = videoType,
                    subtitleTracks = subtitles,
                    title = imdbId
                )
            )
        } catch (e: Exception) {
            Log.e(TAG, "Error extracting video", e)
            Result.failure(VideoExtractionException(e.message ?: "Unknown error", e))
        }
    }
    
    private fun fetchHtml(url: String): String {
        val connection = URL(url).openConnection() as HttpURLConnection
        connection.apply {
            requestMethod = "GET"
            connectTimeout = TIMEOUT_MS
            readTimeout = TIMEOUT_MS
            setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
            setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
            setRequestProperty("Accept-Language", "en-US,en;q=0.5")
            setRequestProperty("Referer", PLAYIMDB_BASE)
            instanceFollowRedirects = true
        }
        
        val responseCode = connection.responseCode
        Log.d(TAG, "Response code: $responseCode")
        
        if (responseCode != HttpURLConnection.HTTP_OK) {
            throw VideoExtractionException("HTTP error: $responseCode")
        }
        
        return connection.inputStream.bufferedReader().use { it.readText() }
    }
    
    private fun extractVideoUrl(doc: org.jsoup.nodes.Document): String? {
        val videoElement = doc.selectFirst("video")
        if (videoElement != null) {
            val src = videoElement.attr("src")
            if (src.isNotEmpty()) {
                Log.d(TAG, "Found video[src]: $src")
                return src
            }
            
            val sourceElements = videoElement.select("source")
            for (source in sourceElements) {
                val srcAttr = source.attr("src")
                if (srcAttr.isNotEmpty() && isValidVideoUrl(srcAttr)) {
                    Log.d(TAG, "Found source[src]: $srcAttr")
                    return srcAttr
                }
            }
        }
        
        val scripts = doc.select("script")
        for (script in scripts) {
            val scriptContent = script.html()
            val urls = extractUrlsFromScript(scriptContent)
            for (url in urls) {
                if (isValidVideoUrl(url)) {
                    Log.d(TAG, "Found URL in script: $url")
                    return url
                }
            }
        }
        
        val allElements = doc.select("*[src], *[href], *[data-src], *[data-url]")
        for (elem in allElements) {
            val possibleUrl = elem.attr("src")
                .ifEmpty { elem.attr("href") }
                .ifEmpty { elem.attr("data-src") }
                .ifEmpty { elem.attr("data-url") }
            
            if (possibleUrl.isNotEmpty() && isValidVideoUrl(possibleUrl)) {
                Log.d(TAG, "Found URL in element: $possibleUrl")
                return possibleUrl
            }
        }
        
        val htmlText = doc.html()
        val m3u8Pattern = Regex("https?://[^\"'<>\\s]+\\.m3u8[^\"'<>\\s]*")
        val m3u8Match = m3u8Pattern.find(htmlText)
        if (m3u8Match != null) {
            Log.d(TAG, "Found .m3u8 via regex: ${m3u8Match.value}")
            return m3u8Match.value
        }
        
        val mp4Pattern = Regex("https?://[^\"'<>\\s]+\\.mp4[^\"'<>\\s]*")
        val mp4Match = mp4Pattern.find(htmlText)
        if (mp4Match != null) {
            Log.d(TAG, "Found .mp4 via regex: ${mp4Match.value}")
            return mp4Match.value
        }
        
        return null
    }
    
    private fun extractUrlsFromScript(scriptContent: String): List<String> {
        val urlPattern = Regex("https?://[^\"'<>\\s]+")
        return urlPattern.findAll(scriptContent)
            .map { it.value }
            .filter { isValidVideoUrl(it) }
            .toList()
    }
    
    private fun isValidVideoUrl(url: String): Boolean {
        return url.contains(".m3u8") || 
               url.contains(".mp4") || 
               url.contains(".mkv") ||
               url.contains("stream") ||
               url.contains("video") ||
               url.contains("player")
    }
    
    private fun determineVideoType(url: String): VideoType {
        return when {
            url.contains(".m3u8") -> VideoType.HLS
            url.contains(".mp4") -> VideoType.MP4
            url.contains(".mpd") -> VideoType.DASH
            else -> VideoType.UNKNOWN
        }
    }
    
    private fun extractSubtitles(doc: org.jsoup.nodes.Document): List<SubtitleTrack> {
        val tracks = mutableListOf<SubtitleTrack>()
        
        val trackElements = doc.select("track")
        for (track in trackElements) {
            val src = track.attr("src")
            val srclang = track.attr("srclang")
            val label = track.attr("label").ifEmpty { srclang }
            val isDefault = track.attr("default") == "default"
            
            if (src.isNotEmpty()) {
                tracks.add(
                    SubtitleTrack(
                        url = src,
                        language = srclang,
                        label = label,
                        isDefault = isDefault
                    )
                )
                Log.d(TAG, "Found subtitle: $srclang - $src")
            }
        }
        
        return tracks
    }
}

class VideoExtractionException(message: String, cause: Throwable? = null) : Exception(message, cause)