use std::path::Path;
use regex::Regex;
use anyhow::{Result, anyhow};

/// 文件名序号解析工具
/// 遵循 Tauri 开发规范的工具函数设计原则
pub struct FilenameUtils;

impl FilenameUtils {
    /// 从文件名中提取序号
    /// 支持多种文件名格式：
    /// - name_001.ext -> 001
    /// - name001.ext -> 001  
    /// - name-001.ext -> 001
    /// - 001_name.ext -> 001
    /// - name_001_suffix.ext -> 001
    pub fn extract_sequence_number(file_path: &str) -> Option<String> {
        let path = Path::new(file_path);
        let filename = path.file_stem()?.to_str()?;

        // 首先检查是否以3位数字开头（最高优先级）
        if let Ok(regex) = Regex::new(r"^(\d{3})_") {
            if let Some(captures) = regex.captures(filename) {
                if let Some(sequence) = captures.get(1) {
                    return Some(sequence.as_str().to_string());
                }
            }
        }

        // 然后按优先级检查其他模式（确保是恰好3位数字）
        let patterns = vec![
            r"_(\d{3})$",               // name_001 (文件名结尾)
            r"_(\d{3})_",               // name_001_suffix (中间位置)
            r"_(\d{3})-",               // name_001-suffix (下划线后跟连字符)
            r"-(\d{3})$",               // name-001 (结尾)
            r"-(\d{3})-",               // name-001-suffix
            r"v(\d{3})$",               // namev001 (v后跟3位数字结尾)
            r"[a-zA-Z](\d{3})$",        // name001 (字母后跟3位数字结尾)
        ];

        // 对于非开头的模式，选择最右边的匹配
        let mut rightmost_match: Option<(usize, String)> = None;

        for pattern in patterns {
            if let Ok(regex) = Regex::new(pattern) {
                for captures in regex.captures_iter(filename) {
                    if let Some(sequence_match) = captures.get(1) {
                        let position = sequence_match.start();
                        let sequence = sequence_match.as_str().to_string();

                        if rightmost_match.is_none() || position > rightmost_match.as_ref().unwrap().0 {
                            rightmost_match = Some((position, sequence));
                        }
                    }
                }
            }
        }

        rightmost_match.map(|(_, sequence)| sequence)
    }
    
    /// 检查文件名是否包含指定序号
    pub fn has_sequence_number(file_path: &str, target_sequence: &str) -> bool {
        if let Some(sequence) = Self::extract_sequence_number(file_path) {
            sequence == target_sequence
        } else {
            false
        }
    }
    
    /// 检查文件名是否包含序号001
    pub fn has_sequence_001(file_path: &str) -> bool {
        Self::has_sequence_number(file_path, "001")
    }
    
    /// 从文件路径中提取文件名（不含路径）
    pub fn extract_filename(file_path: &str) -> String {
        Path::new(file_path)
            .file_name()
            .and_then(|name| name.to_str())
            .unwrap_or("unknown")
            .to_string()
    }
    
    /// 从文件路径中提取文件名（不含扩展名）
    pub fn extract_filename_without_extension(file_path: &str) -> String {
        Path::new(file_path)
            .file_stem()
            .and_then(|name| name.to_str())
            .unwrap_or("unknown")
            .to_string()
    }
    
    /// 验证序号格式（必须是3位数字）
    pub fn is_valid_sequence_format(sequence: &str) -> bool {
        if sequence.len() != 3 {
            return false;
        }
        
        sequence.chars().all(|c| c.is_ascii_digit())
    }
    
    /// 格式化序号为3位数字格式
    pub fn format_sequence_number(number: u32) -> Result<String> {
        if number > 999 {
            return Err(anyhow!("序号不能超过999: {}", number));
        }
        
        Ok(format!("{:03}", number))
    }
    
    /// 解析序号字符串为数字
    pub fn parse_sequence_number(sequence: &str) -> Result<u32> {
        if !Self::is_valid_sequence_format(sequence) {
            return Err(anyhow!("无效的序号格式: {}", sequence));
        }
        
        sequence.parse::<u32>()
            .map_err(|e| anyhow!("解析序号失败: {}", e))
    }
    
    /// 生成带序号的文件名
    pub fn generate_filename_with_sequence(
        base_name: &str,
        sequence: u32,
        extension: &str,
    ) -> Result<String> {
        let formatted_sequence = Self::format_sequence_number(sequence)?;
        Ok(format!("{}_{}.{}", base_name, formatted_sequence, extension))
    }
    
    /// 检查文件是否为视频文件
    pub fn is_video_file(file_path: &str) -> bool {
        let video_extensions = vec![
            "mp4", "avi", "mov", "mkv", "wmv", "flv", "webm", "m4v", "3gp", "ts", "mts"
        ];
        
        if let Some(extension) = Path::new(file_path).extension() {
            if let Some(ext_str) = extension.to_str() {
                return video_extensions.contains(&ext_str.to_lowercase().as_str());
            }
        }
        
        false
    }
    
    /// 从文件路径列表中筛选出包含指定序号的视频文件
    pub fn filter_videos_by_sequence(
        file_paths: &[String],
        target_sequence: &str,
    ) -> Vec<String> {
        file_paths
            .iter()
            .filter(|path| Self::is_video_file(path))
            .filter(|path| Self::has_sequence_number(path, target_sequence))
            .cloned()
            .collect()
    }
    
    /// 从文件路径列表中筛选出包含序号001的视频文件
    pub fn filter_videos_with_sequence_001(file_paths: &[String]) -> Vec<String> {
        Self::filter_videos_by_sequence(file_paths, "001")
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_extract_sequence_number() {
        // 测试各种文件名格式
        assert_eq!(FilenameUtils::extract_sequence_number("video_001.mp4"), Some("001".to_string()));
        assert_eq!(FilenameUtils::extract_sequence_number("video001.mp4"), Some("001".to_string()));
        assert_eq!(FilenameUtils::extract_sequence_number("video-001.mp4"), Some("001".to_string()));
        assert_eq!(FilenameUtils::extract_sequence_number("001_video.mp4"), Some("001".to_string()));
        assert_eq!(FilenameUtils::extract_sequence_number("video_001_final.mp4"), Some("001".to_string()));
        
        // 测试无序号的情况
        assert_eq!(FilenameUtils::extract_sequence_number("video.mp4"), None);
        assert_eq!(FilenameUtils::extract_sequence_number("video_1.mp4"), None); // 不是3位数
        assert_eq!(FilenameUtils::extract_sequence_number("video_abc.mp4"), None); // 不是数字
    }

    #[test]
    fn test_has_sequence_001() {
        assert!(FilenameUtils::has_sequence_001("video_001.mp4"));
        assert!(FilenameUtils::has_sequence_001("001_video.mp4"));
        assert!(!FilenameUtils::has_sequence_001("video_002.mp4"));
        assert!(!FilenameUtils::has_sequence_001("video.mp4"));
    }

    #[test]
    fn test_is_valid_sequence_format() {
        assert!(FilenameUtils::is_valid_sequence_format("001"));
        assert!(FilenameUtils::is_valid_sequence_format("123"));
        assert!(FilenameUtils::is_valid_sequence_format("999"));
        
        assert!(!FilenameUtils::is_valid_sequence_format("1"));
        assert!(!FilenameUtils::is_valid_sequence_format("12"));
        assert!(!FilenameUtils::is_valid_sequence_format("1234"));
        assert!(!FilenameUtils::is_valid_sequence_format("abc"));
    }

    #[test]
    fn test_format_sequence_number() {
        assert_eq!(FilenameUtils::format_sequence_number(1).unwrap(), "001");
        assert_eq!(FilenameUtils::format_sequence_number(42).unwrap(), "042");
        assert_eq!(FilenameUtils::format_sequence_number(999).unwrap(), "999");
        
        assert!(FilenameUtils::format_sequence_number(1000).is_err());
    }

    #[test]
    fn test_is_video_file() {
        assert!(FilenameUtils::is_video_file("video.mp4"));
        assert!(FilenameUtils::is_video_file("video.MP4")); // 大小写不敏感
        assert!(FilenameUtils::is_video_file("video.avi"));
        assert!(FilenameUtils::is_video_file("video.mov"));
        
        assert!(!FilenameUtils::is_video_file("image.jpg"));
        assert!(!FilenameUtils::is_video_file("audio.mp3"));
        assert!(!FilenameUtils::is_video_file("document.txt"));
    }

    #[test]
    fn test_filter_videos_with_sequence_001() {
        let files = vec![
            "video_001.mp4".to_string(),
            "video_002.mp4".to_string(),
            "image_001.jpg".to_string(),
            "audio_001.mp3".to_string(),
            "video.mp4".to_string(),
        ];

        let result = FilenameUtils::filter_videos_with_sequence_001(&files);
        assert_eq!(result.len(), 1);
        assert_eq!(result[0], "video_001.mp4");
    }

    #[test]
    fn test_extract_sequence_number_edge_cases() {
        // 测试路径分隔符
        assert_eq!(FilenameUtils::extract_sequence_number("C:\\videos\\test_001.mp4"), Some("001".to_string()));
        assert_eq!(FilenameUtils::extract_sequence_number("/home/user/videos/test_001.mp4"), Some("001".to_string()));

        // 测试多个数字序列
        assert_eq!(FilenameUtils::extract_sequence_number("video_123_001.mp4"), Some("001".to_string()));
        assert_eq!(FilenameUtils::extract_sequence_number("001_video_456.mp4"), Some("001".to_string()));

        // 测试边界数字
        assert_eq!(FilenameUtils::extract_sequence_number("video_000.mp4"), Some("000".to_string()));
        assert_eq!(FilenameUtils::extract_sequence_number("video_999.mp4"), Some("999".to_string()));

        // 测试无效格式
        assert_eq!(FilenameUtils::extract_sequence_number("video_0001.mp4"), None); // 4位数字
        assert_eq!(FilenameUtils::extract_sequence_number("video_01.mp4"), None);   // 2位数字
        assert_eq!(FilenameUtils::extract_sequence_number("video_1.mp4"), None);    // 1位数字
    }

    #[test]
    fn test_has_sequence_number_various_formats() {
        // 测试不同的分隔符
        assert!(FilenameUtils::has_sequence_number("video_001.mp4", "001"));
        assert!(FilenameUtils::has_sequence_number("video-001.mp4", "001"));
        assert!(FilenameUtils::has_sequence_number("001_video.mp4", "001"));
        assert!(FilenameUtils::has_sequence_number("video001.mp4", "001"));

        // 测试不匹配的情况
        assert!(!FilenameUtils::has_sequence_number("video_002.mp4", "001"));
        assert!(!FilenameUtils::has_sequence_number("video.mp4", "001"));
        assert!(!FilenameUtils::has_sequence_number("video_abc.mp4", "001"));
    }

    #[test]
    fn test_parse_sequence_number() {
        assert_eq!(FilenameUtils::parse_sequence_number("001").unwrap(), 1);
        assert_eq!(FilenameUtils::parse_sequence_number("042").unwrap(), 42);
        assert_eq!(FilenameUtils::parse_sequence_number("999").unwrap(), 999);
        assert_eq!(FilenameUtils::parse_sequence_number("000").unwrap(), 0);

        // 测试无效格式
        assert!(FilenameUtils::parse_sequence_number("1").is_err());
        assert!(FilenameUtils::parse_sequence_number("12").is_err());
        assert!(FilenameUtils::parse_sequence_number("1234").is_err());
        assert!(FilenameUtils::parse_sequence_number("abc").is_err());
        assert!(FilenameUtils::parse_sequence_number("").is_err());
    }

    #[test]
    fn test_generate_filename_with_sequence() {
        assert_eq!(
            FilenameUtils::generate_filename_with_sequence("video", 1, "mp4").unwrap(),
            "video_001.mp4"
        );
        assert_eq!(
            FilenameUtils::generate_filename_with_sequence("test", 42, "avi").unwrap(),
            "test_042.avi"
        );
        assert_eq!(
            FilenameUtils::generate_filename_with_sequence("movie", 999, "mkv").unwrap(),
            "movie_999.mkv"
        );

        // 测试超出范围的序号
        assert!(FilenameUtils::generate_filename_with_sequence("video", 1000, "mp4").is_err());
    }

    #[test]
    fn test_extract_filename_functions() {
        let test_path = "C:\\Users\\test\\videos\\my_video_001.mp4";

        assert_eq!(FilenameUtils::extract_filename(test_path), "my_video_001.mp4");
        assert_eq!(FilenameUtils::extract_filename_without_extension(test_path), "my_video_001");

        // 测试Unix路径
        let unix_path = "/home/user/videos/my_video_001.mp4";
        assert_eq!(FilenameUtils::extract_filename(unix_path), "my_video_001.mp4");
        assert_eq!(FilenameUtils::extract_filename_without_extension(unix_path), "my_video_001");

        // 测试无效路径
        assert_eq!(FilenameUtils::extract_filename(""), "unknown");
        assert_eq!(FilenameUtils::extract_filename_without_extension(""), "unknown");
    }

    #[test]
    fn test_filter_videos_by_sequence() {
        let files = vec![
            "video_001.mp4".to_string(),
            "video_002.mp4".to_string(),
            "video_003.avi".to_string(),
            "image_001.jpg".to_string(),
            "audio_002.mp3".to_string(),
            "document_002.txt".to_string(),
            "movie-002.mkv".to_string(),
        ];

        let result_001 = FilenameUtils::filter_videos_by_sequence(&files, "001");
        assert_eq!(result_001.len(), 1);
        assert_eq!(result_001[0], "video_001.mp4");

        let result_002 = FilenameUtils::filter_videos_by_sequence(&files, "002");
        assert_eq!(result_002.len(), 2);
        assert!(result_002.contains(&"video_002.mp4".to_string()));
        assert!(result_002.contains(&"movie-002.mkv".to_string()));

        let result_999 = FilenameUtils::filter_videos_by_sequence(&files, "999");
        assert_eq!(result_999.len(), 0);
    }

    #[test]
    fn test_complex_filename_patterns() {
        // 测试复杂的文件名模式
        assert_eq!(FilenameUtils::extract_sequence_number("2024_01_15_video_001_final.mp4"), Some("001".to_string()));
        assert_eq!(FilenameUtils::extract_sequence_number("project-v2-scene_042-take1.avi"), Some("042".to_string()));
        assert_eq!(FilenameUtils::extract_sequence_number("001_opening_scene_HD.mkv"), Some("001".to_string()));
        assert_eq!(FilenameUtils::extract_sequence_number("movie_trailer_v001.mp4"), Some("001".to_string()));

        // 测试不应该匹配的模式
        assert_eq!(FilenameUtils::extract_sequence_number("video_2024_01_15.mp4"), None); // 年份不应该匹配
        assert_eq!(FilenameUtils::extract_sequence_number("1080p_video.mp4"), None);      // 分辨率不应该匹配
        assert_eq!(FilenameUtils::extract_sequence_number("video_60fps.mp4"), None);      // 帧率不应该匹配
    }
}
