//! 阅读进度同步模块
//! 
//! 支持本地/云端进度同步、多设备同步等功能

use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use chrono::{DateTime, Utc};

/// 阅读进度
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReadingProgress {
    /// 文档路径/ID
    pub document_id: String,
    /// 当前页码
    pub current_page: usize,
    /// 总页数
    pub total_pages: usize,
    /// 进度百分比 (0-100)
    pub percentage: f32,
    /// 最后阅读位置（字符偏移）
    pub position: usize,
    /// 最后阅读时间
    pub last_read_at: DateTime<Utc>,
    /// 设备标识
    pub device_id: Option<String>,
    /// 是否已同步
    pub synced: bool,
}

impl ReadingProgress {
    pub fn new(document_id: String, total_pages: usize) -> Self {
        Self {
            document_id,
            current_page: 1,
            total_pages,
            percentage: 0.0,
            position: 0,
            last_read_at: Utc::now(),
            device_id: None,
            synced: false,
        }
    }
    
    /// 更新进度
    pub fn update(&mut self, page: usize, position: usize) {
        self.current_page = page;
        self.position = position;
        self.percentage = if self.total_pages > 0 {
            (page as f32 / self.total_pages as f32) * 100.0
        } else {
            0.0
        };
        self.last_read_at = Utc::now();
    }
    
    /// 标记为已同步
    pub fn mark_synced(&mut self) {
        self.synced = true;
    }
}

/// 进度同步管理器
pub struct ProgressManager {
    db: sled::Db,
    device_id: String,
}

impl ProgressManager {
    /// 创建进度管理器
    pub fn new(db_path: &str, device_id: Option<String>) -> Result<Self> {
        let db = sled::open(db_path)?;
        let device_id = device_id.unwrap_or_else(|| Self::generate_device_id());
        
        Ok(Self { db, device_id })
    }
    
    /// 生成设备 ID
    fn generate_device_id() -> String {
        use std::time::{SystemTime, UNIX_EPOCH};
        let timestamp = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap()
            .as_millis();
        format!("device_{}", timestamp)
    }
    
    /// 获取设备 ID
    pub fn get_device_id(&self) -> &str {
        &self.device_id
    }
    
    /// 保存进度
    pub fn save_progress(&self, progress: &ReadingProgress) -> Result<()> {
        let key = format!("progress:{}", progress.document_id);
        let value = serde_json::to_vec(progress)?;
        self.db.insert(key, value)?;
        Ok(())
    }
    
    /// 获取进度
    pub fn get_progress(&self, document_id: &str) -> Result<Option<ReadingProgress>> {
        let key = format!("progress:{}", document_id);
        match self.db.get(key)? {
            Some(value) => {
                let progress: ReadingProgress = serde_json::from_slice(&value)?;
                Ok(Some(progress))
            }
            None => Ok(None),
        }
    }
    
    /// 更新进度
    pub fn update_progress(
        &self,
        document_id: &str,
        total_pages: usize,
        page: usize,
        position: usize,
    ) -> Result<ReadingProgress> {
        let mut progress = match self.get_progress(document_id)? {
            Some(p) => p,
            None => ReadingProgress::new(document_id.to_string(), total_pages),
        };
        
        progress.update(page, position);
        progress.device_id = Some(self.device_id.clone());
        
        self.save_progress(&progress)?;
        Ok(progress)
    }
    
    /// 获取所有进度
    pub fn get_all_progress(&self) -> Result<Vec<ReadingProgress>> {
        let mut progress_list = Vec::new();
        
        for item in self.db.scan_prefix("progress:") {
            let (_, value) = item?;
            let progress: ReadingProgress = serde_json::from_slice(&value)?;
            progress_list.push(progress);
        }
        
        // 按最后阅读时间排序
        progress_list.sort_by(|a, b| b.last_read_at.cmp(&a.last_read_at));
        
        Ok(progress_list)
    }
    
    /// 获取未同步的进度
    pub fn get_unsynced_progress(&self) -> Result<Vec<ReadingProgress>> {
        let mut unsynced = Vec::new();
        
        for item in self.db.scan_prefix("progress:") {
            let (_, value) = item?;
            let mut progress: ReadingProgress = serde_json::from_slice(&value)?;
            if !progress.synced {
                unsynced.push(progress);
            }
        }
        
        Ok(unsynced)
    }
    
    /// 标记进度为已同步
    pub fn mark_as_synced(&self, document_id: &str) -> Result<()> {
        if let Some(mut progress) = self.get_progress(document_id)? {
            progress.mark_synced();
            self.save_progress(&progress)?;
        }
        Ok(())
    }
    
    /// 合并远程进度（解决冲突）
    pub fn merge_remote_progress(&self, remote: &ReadingProgress) -> Result<()> {
        let local = self.get_progress(&remote.document_id)?;
        
        let should_update = match local {
            None => true,
            Some(local_progress) => {
                // 使用最新的进度
                remote.last_read_at > local_progress.last_read_at
            }
        };
        
        if should_update {
            let mut merged = remote.clone();
            merged.device_id = Some(self.device_id.clone());
            self.save_progress(&merged)?;
        }
        
        Ok(())
    }
    
    /// 导出进度为 JSON
    pub fn export_json(&self) -> Result<String> {
        let progress_list = self.get_all_progress()?;
        let json = serde_json::to_string_pretty(&progress_list)?;
        Ok(json)
    }
    
    /// 从 JSON 导入进度
    pub fn import_json(&self, json: &str) -> Result<()> {
        let progress_list: Vec<ReadingProgress> = serde_json::from_str(json)?;
        
        for progress in progress_list {
            self.save_progress(&progress)?;
        }
        
        Ok(())
    }
    
    /// 删除进度
    pub fn remove_progress(&self, document_id: &str) -> Result<()> {
        let key = format!("progress:{}", document_id);
        self.db.remove(key)?;
        Ok(())
    }
    
    /// 清除所有进度
    pub fn clear_all(&self) -> Result<()> {
        let keys: Vec<Vec<u8>> = self.db.scan_prefix("progress:").map(|item| {
            item.map(|(k, _)| k.to_vec())
        }).collect::<Result<Vec<_>, _>>()?;
        
        for key in keys {
            self.db.remove(key)?;
        }
        
        Ok(())
    }
}

/// 云端同步配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SyncConfig {
    /// 同步服务器 URL
    pub server_url: String,
    /// API 密钥
    pub api_key: Option<String>,
    /// 自动同步间隔（秒）
    pub auto_sync_interval: u64,
    /// 启用自动同步
    pub auto_sync_enabled: bool,
}

impl Default for SyncConfig {
    fn default() -> Self {
        Self {
            server_url: String::new(),
            api_key: None,
            auto_sync_interval: 300, // 5 分钟
            auto_sync_enabled: false,
        }
    }
}

/// 云端同步器
pub struct CloudSync {
    config: SyncConfig,
    progress_manager: ProgressManager,
}

impl CloudSync {
    /// 创建云端同步器
    pub fn new(config: SyncConfig, progress_manager: ProgressManager) -> Self {
        Self {
            config,
            progress_manager,
        }
    }
    
    /// 同步到云端
    pub fn sync_to_cloud(&self) -> Result<()> {
        if self.config.server_url.is_empty() {
            return Ok(()); // 未配置服务器，跳过
        }
        
        let unsynced = self.progress_manager.get_unsynced_progress()?;
        
        if unsynced.is_empty() {
            return Ok(());
        }
        
        let client = reqwest::blocking::Client::new();
        
        for progress in unsynced {
            let url = format!("{}/api/v1/progress", self.config.server_url);
            
            let mut request = client
                .post(&url)
                .json(&progress);
            
            if let Some(api_key) = &self.config.api_key {
                request = request.header("Authorization", format!("Bearer {}", api_key));
            }
            
            let response = request
                .send()
                .context("同步请求失败")?;
            
            if response.status().is_success() {
                self.progress_manager.mark_as_synced(&progress.document_id)?;
            }
        }
        
        Ok(())
    }
    
    /// 从云端同步
    pub fn sync_from_cloud(&self) -> Result<()> {
        if self.config.server_url.is_empty() {
            return Ok(());
        }
        
        let client = reqwest::blocking::Client::new();
        let url = format!("{}/api/v1/progress", self.config.server_url);
        
        let mut request = client.get(&url);
        
        if let Some(api_key) = &self.config.api_key {
            request = request.header("Authorization", format!("Bearer {}", api_key));
        }
        
        let response = request
            .send()
            .context("获取云端进度失败")?;
        
        if !response.status().is_success() {
            return Ok(());
        }
        
        let remote_progress_list: Vec<ReadingProgress> = response.json()
            .context("解析云端进度失败")?;
        
        for remote in remote_progress_list {
            self.progress_manager.merge_remote_progress(&remote)?;
        }
        
        Ok(())
    }
    
    /// 完全同步（双向）
    pub fn sync_all(&self) -> Result<()> {
        self.sync_to_cloud()?;
        self.sync_from_cloud()?;
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_progress_creation() {
        let mut progress = ReadingProgress::new("test_doc".to_string(), 100);
        assert_eq!(progress.current_page, 1);
        assert_eq!(progress.total_pages, 100);
        assert_eq!(progress.percentage, 1.0);
        
        progress.update(50, 1000);
        assert_eq!(progress.current_page, 50);
        assert!((progress.percentage - 50.0).abs() < 0.1);
    }
    
    #[test]
    fn test_device_id_generation() {
        let id1 = ProgressManager::generate_device_id();
        let id2 = ProgressManager::generate_device_id();
        
        // 两次生成的 ID 应该不同（因为时间戳不同）
        assert_ne!(id1, id2);
    }
}
