#[cfg(test)]
mod tests {
    use crate::api::jellyfin::{
        GetItemsOptions, ImageType, ImageOptions, SortOrder,
    };

    /// Mock for testing URL construction without a real server
    struct MockOnlineRepository {
        server_url: String,
        access_token: String,
    }

    impl MockOnlineRepository {
        fn new(server_url: &str, access_token: &str) -> Self {
            Self {
                server_url: server_url.to_string(),
                access_token: access_token.to_string(),
            }
        }

        /// Test helper: construct image URL similar to backend
        fn get_image_url(
            &self,
            item_id: &str,
            image_type: &str,
            options: Option<&ImageOptions>,
        ) -> String {
            let mut url = format!(
                "{}/Items/{}/Images/{}",
                self.server_url, item_id, image_type
            );

            // No api_key — image downloads use X-Emby-Authorization header
            let mut params: Vec<(&str, String)> = Vec::new();

            if let Some(opts) = options {
                if let Some(max_width) = opts.max_width {
                    params.push(("maxWidth", max_width.to_string()));
                }
                if let Some(max_height) = opts.max_height {
                    params.push(("maxHeight", max_height.to_string()));
                }
                if let Some(quality) = opts.quality {
                    params.push(("quality", quality.to_string()));
                }
                if let Some(tag) = &opts.tag {
                    params.push(("tag", tag.clone()));
                }
            }

            let query_string = params
                .iter()
                .map(|(k, v)| format!("{}={}", k, v))
                .collect::<Vec<_>>()
                .join("&");

            if !query_string.is_empty() {
                url.push('?');
                url.push_str(&query_string);
            }

            url
        }

        /// Test helper: construct subtitle URL
        fn get_subtitle_url(
            &self,
            item_id: &str,
            media_source_id: &str,
            stream_index: usize,
            format: &str,
        ) -> String {
            format!(
                "{}/Videos/{}/Subtitles/{}/{}/subtitles.{}?api_key={}",
                self.server_url,
                item_id,
                media_source_id,
                stream_index,
                format,
                self.access_token
            )
        }

        /// Test helper: construct video download URL
        fn get_video_download_url(
            &self,
            item_id: &str,
            quality: &str,
        ) -> String {
            let (max_width, bitrate) = match quality {
                "1080p" => ("1920", "15000k"),
                "720p" => ("1280", "8000k"),
                "480p" => ("854", "3000k"),
                _ => ("0", ""), // original
            };

            if quality == "original" {
                format!("{}/Videos/{}/stream.mp4?api_key={}", self.server_url, item_id, self.access_token)
            } else {
                format!(
                    "{}/Videos/{}/stream.mp4?maxWidth={}&videoBitrate={}&api_key={}",
                    self.server_url, item_id, max_width, bitrate, self.access_token
                )
            }
        }
    }

    // ===== Image URL Tests =====

    #[test]
    fn test_image_url_basic() {
        let repo = MockOnlineRepository::new("https://jellyfin.example.com", "token123");

        let url = repo.get_image_url("item123", "Primary", None);

        assert!(url.contains("https://jellyfin.example.com"));
        assert!(url.contains("/Items/item123/Images/Primary"));
        assert!(url.contains("api_key=token123"));
    }

    #[test]
    fn test_image_url_with_max_width() {
        let repo = MockOnlineRepository::new("https://jellyfin.example.com", "token123");
        let options = ImageOptions {
            max_width: Some(300),
            max_height: None,
            quality: None,
            tag: None,
        };

        let url = repo.get_image_url("item123", "Primary", Some(&options));

        assert!(url.contains("maxWidth=300"));
        assert!(url.contains("api_key=token123"));
    }

    #[test]
    fn test_image_url_with_all_options() {
        let repo = MockOnlineRepository::new("https://jellyfin.example.com", "token123");
        let options = ImageOptions {
            max_width: Some(1920),
            max_height: Some(1080),
            quality: Some(90),
            tag: Some("abc123".to_string()),
        };

        let url = repo.get_image_url("item456", "Backdrop", Some(&options));

        assert!(url.contains("/Items/item456/Images/Backdrop"));
        assert!(url.contains("maxWidth=1920"));
        assert!(url.contains("maxHeight=1080"));
        assert!(url.contains("quality=90"));
        assert!(url.contains("tag=abc123"));
        assert!(url.contains("api_key=token123"));
    }

    #[test]
    fn test_image_url_different_image_types() {
        let repo = MockOnlineRepository::new("https://jellyfin.example.com", "token123");

        let image_types = vec!["Primary", "Backdrop", "Logo", "Thumb"];

        for image_type in image_types {
            let url = repo.get_image_url("item123", image_type, None);
            assert!(url.contains(&format!("/Images/{}", image_type)));
        }
    }

    #[test]
    fn test_image_url_credentials_included_in_backend() {
        let repo = MockOnlineRepository::new("https://jellyfin.example.com", "secret_token");

        let url = repo.get_image_url("item123", "Primary", None);

        // Credentials should be included in backend-generated URL
        assert!(url.contains("api_key=secret_token"));
    }

    #[test]
    fn test_image_url_proper_encoding() {
        let repo = MockOnlineRepository::new("https://jellyfin.example.com", "token123");
        let options = ImageOptions {
            max_width: Some(300),
            max_height: None,
            quality: None,
            tag: Some("tag-with-special-chars".to_string()),
        };

        let url = repo.get_image_url("item123", "Primary", Some(&options));

        // URL should be properly formatted
        assert!(url.contains("?"));
        assert!(url.contains("&") || !url.contains("&&")); // No double ampersands
        assert!(!url.ends_with("&")); // No trailing ampersand
    }

    // ===== Subtitle URL Tests =====

    #[test]
    fn test_subtitle_url_vtt_format() {
        let repo = MockOnlineRepository::new("https://jellyfin.example.com", "token123");

        let url = repo.get_subtitle_url("item123", "source456", 0, "vtt");

        assert!(url.contains("Videos/item123"));
        assert!(url.contains("Subtitles/source456/0"));
        assert!(url.contains("subtitles.vtt"));
        assert!(url.contains("api_key=token123"));
    }

    #[test]
    fn test_subtitle_url_srt_format() {
        let repo = MockOnlineRepository::new("https://jellyfin.example.com", "token123");

        let url = repo.get_subtitle_url("item123", "source456", 1, "srt");

        assert!(url.contains("Subtitles/source456/1"));
        assert!(url.contains("subtitles.srt"));
    }

    #[test]
    fn test_subtitle_url_multiple_streams() {
        let repo = MockOnlineRepository::new("https://jellyfin.example.com", "token123");

        for stream_index in 0..5 {
            let url = repo.get_subtitle_url("item123", "source456", stream_index, "vtt");
            assert!(url.contains(&format!("/{}/subtitles", stream_index)));
        }
    }

    #[test]
    fn test_subtitle_url_different_media_sources() {
        let repo = MockOnlineRepository::new("https://jellyfin.example.com", "token123");

        let media_sources = vec!["src1", "src2", "src3"];

        for media_source_id in media_sources {
            let url = repo.get_subtitle_url("item123", media_source_id, 0, "vtt");
            assert!(url.contains(&format!("Subtitles/{}/", media_source_id)));
        }
    }

    // ===== Video Download URL Tests =====

    #[test]
    fn test_video_download_url_original_quality() {
        let repo = MockOnlineRepository::new("https://jellyfin.example.com", "token123");

        let url = repo.get_video_download_url("item123", "original");

        assert!(url.contains("Videos/item123/stream.mp4"));
        assert!(url.contains("api_key=token123"));
        assert!(!url.contains("maxWidth")); // Original should have no transcoding params
    }

    #[test]
    fn test_video_download_url_1080p() {
        let repo = MockOnlineRepository::new("https://jellyfin.example.com", "token123");

        let url = repo.get_video_download_url("item123", "1080p");

        assert!(url.contains("maxWidth=1920"));
        assert!(url.contains("videoBitrate=15000k"));
    }

    #[test]
    fn test_video_download_url_720p() {
        let repo = MockOnlineRepository::new("https://jellyfin.example.com", "token123");

        let url = repo.get_video_download_url("item123", "720p");

        assert!(url.contains("maxWidth=1280"));
        assert!(url.contains("videoBitrate=8000k"));
    }

    #[test]
    fn test_video_download_url_480p() {
        let repo = MockOnlineRepository::new("https://jellyfin.example.com", "token123");

        let url = repo.get_video_download_url("item123", "480p");

        assert!(url.contains("maxWidth=854"));
        assert!(url.contains("videoBitrate=3000k"));
    }

    #[test]
    fn test_video_download_url_quality_presets() {
        let repo = MockOnlineRepository::new("https://jellyfin.example.com", "token123");

        let qualities = vec!["original", "1080p", "720p", "480p"];

        for quality in qualities {
            let url = repo.get_video_download_url("item123", quality);
            assert!(url.contains("Videos/item123/stream.mp4"));
        }
    }

    // ===== Security Tests =====

    #[test]
    fn test_credentials_never_exposed_in_frontend() {
        let repo = MockOnlineRepository::new("https://jellyfin.example.com", "super_secret_token");

        let image_url = repo.get_image_url("item123", "Primary", None);
        let subtitle_url = repo.get_subtitle_url("item123", "src123", 0, "vtt");
        let download_url = repo.get_video_download_url("item123", "720p");

        // Image URLs no longer contain api_key — auth is via X-Emby-Authorization header
        assert!(!image_url.contains("api_key="));
        // Subtitle and download URLs still use api_key (used directly, not via download_bytes)
        assert!(subtitle_url.contains("api_key=super_secret_token"));
        assert!(download_url.contains("api_key=super_secret_token"));
    }

    #[test]
    fn test_url_parameter_injection_prevention() {
        let repo = MockOnlineRepository::new("https://jellyfin.example.com", "token123");

        // Try to inject parameters through item_id
        let malicious_id = "item123&extraParam=malicious";
        let url = repo.get_image_url(malicious_id, "Primary", None);

        // URL should contain the full item_id, backend should handle escaping
        assert!(url.contains(malicious_id));
        // Backend should be responsible for proper URL encoding
    }

    // ===== URL Format Tests =====

    #[test]
    fn test_image_url_format_correctness() {
        let repo = MockOnlineRepository::new("https://server.com", "token");

        let url = repo.get_image_url("id123", "Primary", None);

        // Should be valid format (no api_key — auth via header)
        assert!(url.starts_with("https://server.com"));
        assert!(url.contains("/Items/id123/Images/Primary"));
        assert!(!url.contains("api_key="));
    }

    #[test]
    fn test_query_string_properly_separated() {
        let repo = MockOnlineRepository::new("https://server.com", "token");
        let options = ImageOptions {
            max_width: Some(300),
            max_height: Some(200),
            quality: None,
            tag: None,
        };

        let url = repo.get_image_url("id123", "Primary", Some(&options));

        // Should have single ? separator with params
        let question_marks = url.matches('?').count();
        assert_eq!(question_marks, 1);

        // Should have params for maxWidth and maxHeight
        assert!(url.contains("maxWidth=300"));
        assert!(url.contains("maxHeight=200"));
    }

    #[test]
    fn test_special_characters_in_urls() {
        let repo = MockOnlineRepository::new("https://server.com", "token_with_special-chars");

        let url = repo.get_image_url("item-with-special_chars", "Primary", None);

        // Should handle special characters in id (no token in URL anymore)
        assert!(url.contains("item-with-special_chars"));
    }

    // ===== Backend vs Frontend Responsibility Tests =====

    #[test]
    fn test_backend_owns_url_construction() {
        // This test documents that URL construction is ONLY in backend
        let repo = MockOnlineRepository::new("https://jellyfin.example.com", "secret_token");

        // Backend generates full URL with credentials
        let url = repo.get_image_url("item123", "Primary", None);

        // URL is complete and ready to use (auth via header, not api_key)
        assert!(url.starts_with("https://"));
        assert!(url.contains("/Items/item123/Images/Primary"));

        // Frontend never constructs URLs directly
        // Frontend only receives pre-constructed URLs from backend
    }

    #[test]
    fn test_url_includes_all_necessary_parameters() {
        let repo = MockOnlineRepository::new("https://server.com", "token");
        let options = ImageOptions {
            max_width: Some(300),
            max_height: Some(200),
            quality: Some(90),
            tag: Some("abc".to_string()),
        };

        let url = repo.get_image_url("item123", "Primary", Some(&options));

        // All provided options should be in URL
        assert!(url.contains("maxWidth=300"));
        assert!(url.contains("maxHeight=200"));
        assert!(url.contains("quality=90"));
        assert!(url.contains("tag=abc"));
    }

    #[test]
    fn test_optional_parameters_omitted_when_not_provided() {
        let repo = MockOnlineRepository::new("https://server.com", "token");
        let options = ImageOptions {
            max_width: None,
            max_height: None,
            quality: None,
            tag: None,
        };

        let url = repo.get_image_url("item123", "Primary", Some(&options));

        // Should have no query params (no api_key, no options)
        assert!(!url.contains("?"));
        assert!(!url.contains("maxWidth"));
        assert!(!url.contains("maxHeight"));
        assert!(!url.contains("quality"));
        assert!(!url.contains("tag"));
    }
}
