"""
进度计算服务 - M24

功能: 显示项目真实进度

进度计算公式:
进度 = (需求完成数/需求总数 × 40%) + (BUG解决数/BUG总数 × 30%) + (TODO完成数/TODO总数 × 30%)

"""

import logging
from datetime import datetime
from typing import Dict, List, Optional
from dataclasses import dataclass, field


logger = logging.getLogger(__name__)


@dataclass
class RequirementsProgress:
    """需求进度"""
    total: int = 0
    completed: int = 0
    in_progress: int = 0
    pending: int = 0
    progress_percentage: int = 0


@dataclass
class BugsProgress:
    """BUG进度"""
    total: int = 0
    resolved: int = 0
    open: int = 0
    progress_percentage: int = 0


@dataclass
class TodosProgress:
    """TODO进度"""
    total: int = 0
    completed: int = 0
    pending: int = 0
    progress_percentage: int = 0


@dataclass
class ProjectProgress:
    """项目进度"""
    project_name: str
    overall_progress: int = 0
    requirements: RequirementsProgress = field(default_factory=RequirementsProgress)
    bugs: BugsProgress = field(default_factory=BugsProgress)
    todos: TodosProgress = field(default_factory=TodosProgress)
    updated_at: datetime = None


@dataclass
class ProjectsSummary:
    """项目汇总"""
    total_projects: int = 0
    active_projects: int = 0
    avg_progress: int = 0
    projects: List[Dict] = field(default_factory=list)


class ProgressService:
    """进度计算服务"""
    
    def __init__(self, client=None):
        """
        初始化
        
        Args:
            client: OcCollabClient实例
        """
        self.client = client
        self.logger = logging.getLogger(__name__)
        self._requirements_weight = 0.4
        self._bugs_weight = 0.3
        self._todos_weight = 0.3
    
    def get_project_progress(self, project_name: str) -> ProjectProgress:
        """
        获取项目进度
        
        Args:
            project_name: 项目名称
            
        Returns:
            ProjectProgress: 项目进度
        """
        progress = ProjectProgress(
            project_name=project_name,
            updated_at=datetime.now()
        )
        
        if not self.client:
            self.logger.warning("OcCollabClient未初始化")
            return progress
        
        try:
            oc_progress = self.client.get_project_progress(project_name)
            
            progress.requirements = RequirementsProgress(
                total=oc_progress.requirements_total,
                completed=oc_progress.requirements_completed,
                in_progress=oc_progress.requirements_in_progress,
                pending=oc_progress.requirements_total - oc_progress.requirements_completed - oc_progress.requirements_in_progress
            )
            
            progress.bugs = BugsProgress(
                total=oc_progress.bugs_total,
                resolved=oc_progress.bugs_resolved,
                open=oc_progress.bugs_total - oc_progress.bugs_resolved
            )
            
            progress.todos = TodosProgress(
                total=oc_progress.todos_total,
                completed=oc_progress.todos_completed,
                pending=oc_progress.todos_total - oc_progress.todos_completed
            )
            
            progress.overall_progress = self.calculate_overall_progress(progress)
            
        except Exception as e:
            self.logger.error(f"获取项目进度失败: {e}")
        
        return progress
    
    def calculate_overall_progress(self, progress: ProjectProgress) -> int:
        """
        计算综合进度百分比
        
        Args:
            progress: 项目进度数据
            
        Returns:
            int: 进度百分比 (0-100)
        """
        req_progress = 0
        if progress.requirements.total > 0:
            req_progress = progress.requirements.completed / progress.requirements.total
        
        bug_progress = 0
        if progress.bugs.total > 0:
            bug_progress = progress.bugs.resolved / progress.bugs.total
        
        todo_progress = 0
        if progress.todos.total > 0:
            todo_progress = progress.todos.completed / progress.todos.total
        
        overall = (req_progress * self._requirements_weight + 
                   bug_progress * self._bugs_weight + 
                   todo_progress * self._todos_weight)
        
        return int(overall * 100)
    
    def get_all_projects_summary(self, project_names: List[str] = None) -> ProjectsSummary:
        """
        获取所有项目汇总
        
        Args:
            project_names: 项目名称列表（可选，默认所有项目）
            
        Returns:
            ProjectsSummary: 项目汇总
        """
        summary = ProjectsSummary()
        
        if not self.client:
            return summary
        
        try:
            if project_names is None:
                project_names = self._get_all_project_names()
            
            progress_list = []
            for name in project_names:
                progress = self.get_project_progress(name)
                progress_list.append({
                    'name': progress.project_name,
                    'progress': progress.overall_progress,
                    'requirements': {
                        'total': progress.requirements.total,
                        'completed': progress.requirements.completed
                    },
                    'bugs': {
                        'total': progress.bugs.total,
                        'resolved': progress.bugs.resolved
                    },
                    'todos': {
                        'total': progress.todos.total,
                        'completed': progress.todos.completed
                    }
                })
            
            summary.total_projects = len(progress_list)
            summary.active_projects = len([p for p in progress_list if p['progress'] > 0])
            
            if progress_list:
                summary.avg_progress = int(sum(p['progress'] for p in progress_list) / len(progress_list))
            
            summary.projects = progress_list
            
        except Exception as e:
            self.logger.error(f"获取项目汇总失败: {e}")
        
        return summary
    
    def _get_all_project_names(self) -> List[str]:
        """获取所有项目名称"""
        try:
            if self.client and hasattr(self.client, 'list_projects'):
                projects = self.client.list_projects()
                return [p.get('name', '') for p in projects if p.get('name')]
            return []
        except Exception as e:
            self.logger.error(f"获取项目列表失败: {e}")
            return []
    
    def save_progress_to_db(self, progress: ProjectProgress, db_session=None):
        """
        保存进度到数据库
        
        Args:
            progress: 项目进度
            db_session: 数据库会话
        """
        if not db_session:
            return
        
        try:
            from backend.models.database import Project, ProjectSyncStatus
            
            project = db_session.query(Project).filter(
                Project.name == progress.project_name
            ).first()
            
            if not project:
                return
            
            sync_status = db_session.query(ProjectSyncStatus).filter(
                ProjectSyncStatus.project_id == project.id
            ).first()
            
            if not sync_status:
                sync_status = ProjectSyncStatus(project_id=project.id)
                db_session.add(sync_status)
            
            sync_status.last_sync_time = datetime.now()
            sync_status.sync_status = 'ok'
            sync_status.requirements_total = progress.requirements.total
            sync_status.requirements_completed = progress.requirements.completed
            sync_status.requirements_in_progress = progress.requirements.in_progress
            sync_status.bugs_total = progress.bugs.total
            sync_status.bugs_resolved = progress.bugs.resolved
            sync_status.todos_total = progress.todos.total
            sync_status.todos_completed = progress.todos.completed
            sync_status.progress_percentage = progress.overall_progress
            sync_status.updated_at = datetime.now()
            
            db_session.commit()
            
        except Exception as e:
            self.logger.error(f"保存进度失败: {e}")
            if db_session:
                db_session.rollback()
    
    def get_progress_history(self, project_name: str, days: int = 30) -> List[Dict]:
        """
        获取进度历史
        
        Args:
            project_name: 项目名称
            days: 天数
            
        Returns:
            List[Dict]: 进度历史列表
        """
        from backend.models.database import Project, ProjectSyncStatus
        from datetime import timedelta
        
        try:
            from backend.models.database import get_db
            
            db = next(get_db())
            try:
                project = db.query(Project).filter(Project.name == project_name).first()
                if not project:
                    return []
                
                start_time = datetime.now() - timedelta(days=days)
                
                records = db.query(ProjectSyncStatus).filter(
                    ProjectSyncStatus.project_id == project.id,
                    ProjectSyncStatus.updated_at >= start_time
                ).order_by(ProjectSyncStatus.updated_at.asc()).all()
                
                history = []
                for record in records:
                    history.append({
                        'date': record.updated_at.isoformat(),
                        'progress': record.progress_percentage,
                        'requirements': {
                            'total': record.requirements_total,
                            'completed': record.requirements_completed
                        },
                        'bugs': {
                            'total': record.bugs_total,
                            'resolved': record.bugs_resolved
                        },
                        'todos': {
                            'total': record.todos_total,
                            'completed': record.todos_completed
                        }
                    })
                
                return history
            finally:
                db.close()
        except Exception as e:
            self.logger.error(f"获取进度历史失败: {e}")
            return []
    
    def set_weights(self, requirements: float = None, bugs: float = None, todos: float = None):
        """
        设置权重
        
        Args:
            requirements: 需求权重
            bugs: BUG权重
            todos: TODO权重
        """
        if requirements is not None:
            self._requirements_weight = requirements
        if bugs is not None:
            self._bugs_weight = bugs
        if todos is not None:
            self._todos_weight = todos
        
        total = self._requirements_weight + self._bugs_weight + self._todos_weight
        if total != 1.0:
            self.logger.warning(f"权重之和不为1.0: {total}，将按比例调整")
            if total > 0:
                self._requirements_weight /= total
                self._bugs_weight /= total
                self._todos_weight /= total
