use axum::http::HeaderMap;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ClientCapabilities {
    pub supports_av1: bool,
    pub supports_hevc: bool,
    pub supports_vp9: bool,
    pub max_resolution: String,
    pub device_type: String,
    pub browser: Option<String>,
}

impl ClientCapabilities {
    pub fn detect_from_headers(headers: &HeaderMap) -> Self {
        let user_agent = headers
            .get("user-agent")
            .and_then(|h| h.to_str().ok())
            .unwrap_or("")
            .to_lowercase();

        let accept = headers
            .get("accept")
            .and_then(|h| h.to_str().ok())
            .unwrap_or("")
            .to_lowercase();

        let supports_av1 = Self::detect_av1_support(&user_agent, &accept);
        let supports_hevc = Self::detect_hevc_support(&user_agent);
        let supports_vp9 = Self::detect_vp9_support(&user_agent);
        let (device_type, browser) = Self::parse_device_info(&user_agent);
        let max_resolution = Self::detect_max_resolution(&user_agent, &device_type);

        Self {
            supports_av1,
            supports_hevc,
            supports_vp9,
            max_resolution,
            device_type,
            browser,
        }
    }

    fn detect_av1_support(user_agent: &str, accept: &str) -> bool {
        // Check if the Accept header explicitly mentions AV1
        if accept.contains("codecs=\"av01") || accept.contains("codecs='av01") {
            return true;
        }

        // Safari on Apple Silicon (M3+ or A17+) supports AV1, but only on macOS, not iOS
        if user_agent.contains("safari") && !user_agent.contains("chrome") && !user_agent.contains("mobile") {
            // Desktop Safari - Check for newer Safari versions that might support AV1
            if user_agent.contains("version/17") || user_agent.contains("version/18") {
                return true;
            }
            return false;
        }

        // Chrome 70+ supports AV1
        if user_agent.contains("chrome") {
            if let Some(version) = extract_chrome_version(user_agent) {
                return version >= 70;
            }
        }

        // Firefox 67+ supports AV1
        if user_agent.contains("firefox") {
            if let Some(version) = extract_firefox_version(user_agent) {
                return version >= 67;
            }
        }

        // Edge 79+ (Chromium-based) supports AV1
        if user_agent.contains("edg/") {
            if let Some(version) = extract_edge_version(user_agent) {
                return version >= 79;
            }
        }

        // iOS devices - only A17+ chips support AV1
        if user_agent.contains("iphone") || user_agent.contains("ipad") {
            // Very conservative approach - assume no AV1 support unless explicitly detected
            return false;
        }

        // Android devices - most modern devices support AV1
        if user_agent.contains("android") {
            // Android 10+ generally supports AV1, but be conservative
            return user_agent.contains("android 1"); // Android 10, 11, 12, 13, 14, etc.
        }

        // Default to no AV1 support for unknown clients
        false
    }

    fn detect_hevc_support(user_agent: &str) -> bool {
        // Safari supports HEVC natively
        if user_agent.contains("safari") && !user_agent.contains("chrome") {
            return true;
        }

        // Edge supports HEVC with proper codecs
        if user_agent.contains("edg/") {
            return true;
        }

        // iOS devices support HEVC
        if user_agent.contains("iphone") || user_agent.contains("ipad") {
            return true;
        }

        // Most Android devices support HEVC
        if user_agent.contains("android") {
            return true;
        }

        false
    }

    fn detect_vp9_support(user_agent: &str) -> bool {
        // Chrome supports VP9
        if user_agent.contains("chrome") {
            if let Some(version) = extract_chrome_version(user_agent) {
                return version >= 29;
            }
        }

        // Firefox supports VP9
        if user_agent.contains("firefox") {
            if let Some(version) = extract_firefox_version(user_agent) {
                return version >= 28;
            }
        }

        // Edge supports VP9
        if user_agent.contains("edg/") {
            return true;
        }

        // Safari has limited VP9 support
        if user_agent.contains("safari") && !user_agent.contains("chrome") {
            return false;
        }

        true // Most modern browsers support VP9
    }

    fn parse_device_info(user_agent: &str) -> (String, Option<String>) {
        if user_agent.contains("iphone") {
            ("iOS".to_string(), Some("Safari".to_string()))
        } else if user_agent.contains("ipad") {
            ("iPadOS".to_string(), Some("Safari".to_string()))
        } else if user_agent.contains("android") {
            let browser = if user_agent.contains("chrome") {
                Some("Chrome".to_string())
            } else {
                Some("Android Browser".to_string())
            };
            ("Android".to_string(), browser)
        } else if user_agent.contains("macintosh") {
            let browser = if user_agent.contains("safari") && !user_agent.contains("chrome") {
                Some("Safari".to_string())
            } else if user_agent.contains("chrome") {
                Some("Chrome".to_string())
            } else if user_agent.contains("firefox") {
                Some("Firefox".to_string())
            } else {
                Some("Unknown".to_string())
            };
            ("macOS".to_string(), browser)
        } else if user_agent.contains("windows") {
            let browser = if user_agent.contains("edg/") {
                Some("Edge".to_string())
            } else if user_agent.contains("chrome") {
                Some("Chrome".to_string())
            } else if user_agent.contains("firefox") {
                Some("Firefox".to_string())
            } else {
                Some("Unknown".to_string())
            };
            ("Windows".to_string(), browser)
        } else if user_agent.contains("linux") {
            let browser = if user_agent.contains("chrome") {
                Some("Chrome".to_string())
            } else if user_agent.contains("firefox") {
                Some("Firefox".to_string())
            } else {
                Some("Unknown".to_string())
            };
            ("Linux".to_string(), browser)
        } else {
            ("Unknown".to_string(), None)
        }
    }

    fn detect_max_resolution(_user_agent: &str, device_type: &str) -> String {
        match device_type {
            "iOS" | "iPadOS" => "1080p".to_string(), // Conservative for mobile
            "Android" => "1080p".to_string(),        // Conservative for mobile
            _ => "4K".to_string(),                   // Desktop can handle higher resolutions
        }
    }

    pub fn to_jellyfin_device_profile(&self) -> serde_json::Value {
        serde_json::json!({
            "Name": format!("{} - Custom", self.device_type),
            "Id": format!("custom-{}", self.device_type.to_lowercase()),
            "max_streaming_bitrate": self.get_max_bitrate(),
            "music_streaming_transcoding_bitrate": 192000,
            "transcoding_profiles": self.get_transcoding_profiles(),
            "direct_play_profiles": self.get_direct_play_profiles(),
            "response_profiles": [],
            "container_profiles": [],
            "codec_profiles": self.get_codec_profiles(),
            "subtitle_profiles": [
                {
                    "Format": "srt",
                    "Method": "External"
                },
                {
                    "Format": "vtt", 
                    "Method": "External"
                }
            ]
        })
    }

    fn get_max_bitrate(&self) -> u32 {
        match self.device_type.as_str() {
            "iOS" | "iPadOS" | "Android" => 8_000_000, // 8 Mbps for mobile
            _ => 20_000_000, // 20 Mbps for desktop
        }
    }

    fn get_transcoding_profiles(&self) -> Vec<serde_json::Value> {
        vec![
            serde_json::json!({
                "Container": "mp4",
                "Type": "Video", 
                "video_codec": "h264",
                "audio_codec": "aac",
                "Protocol": "hls",
                "estimate_content_length": false,
                "enable_mpegts_m2ts_mode": false,
                "transcode_seek_info": "Auto",
                "copy_timestamps": false,
                "Context": "Streaming",
                "enable_subtitles_in_manifest": false,
                "max_audio_channels": "2"
            })
        ]
    }

    fn get_direct_play_profiles(&self) -> Vec<serde_json::Value> {
        let mut profiles = vec![
            serde_json::json!({
                "Container": "mp4",
                "Type": "Video",
                "video_codec": "h264",
                "audio_codec": "aac,mp3"
            })
        ];

        if self.supports_hevc {
            profiles.push(serde_json::json!({
                "Container": "mp4",
                "Type": "Video", 
                "video_codec": "hevc",
                "audio_codec": "aac,mp3"
            }));
        }

        if self.supports_vp9 {
            profiles.push(serde_json::json!({
                "Container": "webm",
                "Type": "Video",
                "video_codec": "vp9",
                "audio_codec": "vorbis,opus"
            }));
        }

        if self.supports_av1 {
            profiles.push(serde_json::json!({
                "Container": "mp4",
                "Type": "Video",
                "video_codec": "av1",
                "audio_codec": "aac,mp3,opus"
            }));
            profiles.push(serde_json::json!({
                "Container": "webm", 
                "Type": "Video",
                "video_codec": "av1",
                "audio_codec": "opus"
            }));
        }

        profiles
    }

    fn get_codec_profiles(&self) -> Vec<serde_json::Value> {
        let mut profiles = vec![];

        // H.264 profile
        profiles.push(serde_json::json!({
            "Type": "Video",
            "Codec": "h264",
            "Conditions": [
                {
                    "condition": "less_than_equal",
                    "property": "video_bit_depth", 
                    "value": "8"
                }
            ]
        }));

        if self.supports_hevc {
            profiles.push(serde_json::json!({
                "Type": "Video",
                "Codec": "hevc",
                "Conditions": [
                    {
                        "condition": "less_than_equal",
                        "property": "video_bit_depth",
                        "value": "10"
                    }
                ]
            }));
        }

        if self.supports_av1 {
            profiles.push(serde_json::json!({
                "Type": "Video", 
                "Codec": "av1",
                "Conditions": [
                    {
                        "condition": "less_than_equal",
                        "property": "video_bit_depth",
                        "value": "10"
                    }
                ]
            }));
        }

        profiles
    }
}

fn extract_chrome_version(user_agent: &str) -> Option<u32> {
    if let Some(start) = user_agent.find("chrome/") {
        let version_str = &user_agent[start + 7..];
        if let Some(end) = version_str.find(&[' ', '.'][..]) {
            version_str[..end].parse().ok()
        } else {
            None
        }
    } else {
        None
    }
}

fn extract_firefox_version(user_agent: &str) -> Option<u32> {
    if let Some(start) = user_agent.find("firefox/") {
        let version_str = &user_agent[start + 8..];
        if let Some(end) = version_str.find(&[' ', '.'][..]) {
            version_str[..end].parse().ok()
        } else {
            None
        }
    } else {
        None
    }
}

fn extract_edge_version(user_agent: &str) -> Option<u32> {
    if let Some(start) = user_agent.find("edg/") {
        let version_str = &user_agent[start + 4..];
        if let Some(end) = version_str.find(&[' ', '.'][..]) {
            version_str[..end].parse().ok()
        } else {
            None
        }
    } else {
        None
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use axum::http::{HeaderMap, HeaderName, HeaderValue};

    #[test]
    fn test_chrome_av1_support() {
        let mut headers = HeaderMap::new();
        headers.insert(
            HeaderName::from_static("user-agent"),
            HeaderValue::from_static("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
        );

        let capabilities = ClientCapabilities::detect_from_headers(&headers);
        assert!(capabilities.supports_av1);
        assert!(capabilities.supports_vp9);
    }

    #[test]
    fn test_safari_no_av1_support() {
        let mut headers = HeaderMap::new();
        headers.insert(
            HeaderName::from_static("user-agent"), 
            HeaderValue::from_static("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Version/16.6 Safari/537.36")
        );

        let capabilities = ClientCapabilities::detect_from_headers(&headers);
        assert!(!capabilities.supports_av1);
        assert!(capabilities.supports_hevc);
    }

    #[test]
    fn test_ios_device_detection() {
        let mut headers = HeaderMap::new();
        headers.insert(
            HeaderName::from_static("user-agent"),
            HeaderValue::from_static("Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1")
        );

        let capabilities = ClientCapabilities::detect_from_headers(&headers);
        assert_eq!(capabilities.device_type, "iOS");
        assert!(!capabilities.supports_av1); // Conservative for older iOS
        assert!(capabilities.supports_hevc);
    }
}