"""
Project domain services.

Contains business logic for project-related operations.
"""

from typing import Dict, Any, List
from datetime import datetime, timedelta, timezone
from .models import Project, Milestone, ProjectState
from .exceptions import ProjectValidationError


class ProjectManagementService:
    """Domain service for project management business logic."""

    def determine_project_health(self, project: Project) -> str:
        """Determine project health based on business rules."""
        progress = project.calculate_overall_progress()
        overdue_milestones = project.get_overdue_milestones()
        active_milestones = project.get_active_milestones()

        # Business rules for project health assessment
        if project.state != ProjectState.ACTIVE:
            return "Inactive"

        if progress >= 95:
            return "Excellent"
        elif progress >= 80:
            return "Good"
        elif progress >= 60:
            return "Fair"
        elif len(overdue_milestones) > 0:
            return "At Risk"
        elif len(active_milestones) == 0:
            return "Stalled"
        else:
            return "Needs Attention"

    def calculate_project_velocity(self, project: Project, days_back: int = 30) -> float:
        """Calculate project velocity based on recent milestone completions."""
        completed_milestones = project.get_completed_milestones()
        cutoff_date = datetime.now(timezone.utc) - timedelta(days=days_back)

        # Count milestones completed in the specified period
        # Note: This would need milestone completion dates in a real implementation
        recent_completions = len(completed_milestones)  # Simplified for now

        return recent_completions / (days_back / 7)  # Issues per week

    def identify_bottlenecks(self, project: Project) -> List[str]:
        """Identify potential bottlenecks in the project."""
        bottlenecks = []

        # Check for overdue milestones
        overdue_milestones = project.get_overdue_milestones()
        if overdue_milestones:
            bottlenecks.append(f"Overdue milestones: {len(overdue_milestones)}")

        # Check for milestones with too many open issues
        for milestone in project.get_active_milestones():
            if milestone.open_issues > 20:  # Business rule: threshold for too many issues
                bottlenecks.append(f"Milestone '{milestone.title}' has {milestone.open_issues} open issues")

        # Check for stalled milestones (no progress)
        for milestone in project.get_active_milestones():
            if milestone.total_issues > 0 and milestone.completion_percentage == 0:
                bottlenecks.append(f"Milestone '{milestone.title}' shows no progress")

        return bottlenecks

    def recommend_next_actions(self, project: Project) -> List[str]:
        """Recommend next actions based on project state."""
        recommendations = []
        health = self.determine_project_health(project)

        if health == "At Risk":
            overdue_milestones = project.get_overdue_milestones()
            recommendations.append(f"Address {len(overdue_milestones)} overdue milestone(s)")

        if health == "Stalled":
            recommendations.append("Create new milestones or reactivate existing ones")

        # Check for milestones nearing completion
        for milestone in project.get_active_milestones():
            if milestone.completion_percentage >= 80:
                recommendations.append(f"Focus on completing milestone '{milestone.title}' ({milestone.completion_percentage:.0f}% done)")

        # Check for unbalanced workload
        total_open = project.get_total_open_issues()
        if total_open > 50:  # Business rule: threshold for too many open issues
            recommendations.append(f"Consider breaking down work - {total_open} total open issues")

        return recommendations

    def validate_project_creation(self, name: str, description: str) -> None:
        """Validate project creation according to business rules."""
        if not name or not name.strip():
            raise ProjectValidationError(
                "Project name cannot be empty",
                field="name",
                value=name
            )

        if len(name) > 100:
            raise ProjectValidationError(
                "Project name cannot exceed 100 characters",
                field="name",
                value=name
            )

        if description and len(description) > 1000:
            raise ProjectValidationError(
                "Project description cannot exceed 1000 characters",
                field="description",
                value=description
            )

    def validate_milestone_creation(self, title: str, due_date: datetime = None) -> None:
        """Validate milestone creation according to business rules."""
        if not title or not title.strip():
            raise ProjectValidationError(
                "Milestone title cannot be empty",
                field="title",
                value=title
            )

        if len(title) > 100:
            raise ProjectValidationError(
                "Milestone title cannot exceed 100 characters",
                field="title",
                value=title
            )

        # Business rule: Due date cannot be in the past
        if due_date and due_date < datetime.now(timezone.utc):
            raise ProjectValidationError(
                "Milestone due date cannot be in the past",
                field="due_date",
                value=due_date
            )

    def calculate_milestone_priority(self, milestone: Milestone) -> int:
        """Calculate milestone priority based on business rules."""
        priority_score = 0

        # Higher priority for milestones with more issues
        priority_score += milestone.total_issues * 2

        # Higher priority for milestones with due dates
        if milestone.due_date:
            days_until_due = (milestone.due_date - datetime.now(timezone.utc)).days
            if days_until_due <= 7:
                priority_score += 50  # Very urgent
            elif days_until_due <= 30:
                priority_score += 25  # Urgent
            else:
                priority_score += 10  # Normal

        # Higher priority for milestones closer to completion
        if milestone.completion_percentage >= 75:
            priority_score += 30  # Push to completion

        # Lower priority for stalled milestones
        if milestone.total_issues > 0 and milestone.completion_percentage == 0:
            priority_score -= 20

        return max(0, priority_score)  # Ensure non-negative

    def generate_project_summary(self, project: Project) -> Dict[str, Any]:
        """Generate a comprehensive project summary."""
        health = self.determine_project_health(project)
        bottlenecks = self.identify_bottlenecks(project)
        recommendations = self.recommend_next_actions(project)

        return {
            "name": project.name,
            "state": project.state.value,
            "health": health,
            "overall_progress": project.calculate_overall_progress(),
            "total_milestones": len(project.milestones),
            "active_milestones": len(project.get_active_milestones()),
            "completed_milestones": len(project.get_completed_milestones()),
            "overdue_milestones": len(project.get_overdue_milestones()),
            "total_issues": project.get_total_issues(),
            "open_issues": project.get_total_open_issues(),
            "closed_issues": project.get_total_closed_issues(),
            "bottlenecks": bottlenecks,
            "recommendations": recommendations
        }