"""
Sprint & Backlog Manager
========================
Generated by El Gringo team (chatgpt-coder, grok-coder, gemini-creative).
Fixed integration: added get_summary_stats, get_tasks_for_sprint,
calculate_sprint_completion, get_tasks_completed_since, get_velocity_trend.
"""

import json
import os
import threading
import uuid
from dataclasses import asdict, dataclass, field
from datetime import datetime, timedelta
from pathlib import Path
from typing import Dict, List, Optional

WORKFLOW_DIR = Path(os.path.expanduser("~/.ai-dev-team/workflow/"))
TASKS_FILE = WORKFLOW_DIR / "tasks.json"
SPRINTS_FILE = WORKFLOW_DIR / "sprints.json"

WORKFLOW_DIR.mkdir(parents=True, exist_ok=True)

VALID_STATUSES = ("backlog", "sprint", "in_progress", "review", "done")


@dataclass
class Task:
    id: str = field(default_factory=lambda: str(uuid.uuid4())[:8])
    title: str = ""
    description: str = ""
    status: str = "backlog"
    priority: int = 3
    estimate_hours: float = 0.0
    sprint_id: Optional[str] = None
    project: str = ""
    assignee: str = ""
    created_at: str = field(default_factory=lambda: datetime.now().isoformat())
    updated_at: str = field(default_factory=lambda: datetime.now().isoformat())


@dataclass
class Sprint:
    id: str = field(default_factory=lambda: str(uuid.uuid4())[:8])
    name: str = ""
    start_date: str = field(default_factory=lambda: datetime.now().isoformat())
    end_date: str = field(default_factory=lambda: (datetime.now() + timedelta(days=14)).isoformat())
    goals: List[str] = field(default_factory=list)
    status: str = "active"


class SprintManager:
    def __init__(self):
        self._lock = threading.Lock()
        self.tasks: List[Task] = []
        self.sprints: List[Sprint] = []
        self._load()

    def _load(self):
        with self._lock:
            if TASKS_FILE.exists():
                with TASKS_FILE.open("r") as f:
                    self.tasks = [Task(**t) for t in json.load(f)]
            if SPRINTS_FILE.exists():
                with SPRINTS_FILE.open("r") as f:
                    self.sprints = [Sprint(**s) for s in json.load(f)]

    def _save_tasks(self):
        with self._lock:
            with TASKS_FILE.open("w") as f:
                json.dump([asdict(t) for t in self.tasks], f, indent=2)

    def _save_sprints(self):
        with self._lock:
            with SPRINTS_FILE.open("w") as f:
                json.dump([asdict(s) for s in self.sprints], f, indent=2)

    # --- Core CRUD ---

    def create_task(self, title: str, description: str = "", priority: int = 3,
                    estimate_hours: float = 1.0, project: str = "", assignee: str = "") -> Task:
        task = Task(title=title, description=description, priority=priority,
                    estimate_hours=estimate_hours, project=project, assignee=assignee)
        self.tasks.append(task)
        self._save_tasks()
        return task

    def create_sprint(self, name: str, goals: Optional[List[str]] = None,
                      start_date: Optional[str] = None, end_date: Optional[str] = None) -> Sprint:
        sprint = Sprint(name=name, goals=goals or [])
        if start_date:
            sprint.start_date = start_date
        if end_date:
            sprint.end_date = end_date
        self.sprints.append(sprint)
        self._save_sprints()
        return sprint

    def add_to_sprint(self, sprint_id: str, task_id: str) -> bool:
        task = next((t for t in self.tasks if t.id == task_id), None)
        sprint = next((s for s in self.sprints if s.id == sprint_id), None)
        if not task or not sprint:
            return False
        task.sprint_id = sprint_id
        task.status = "sprint"
        task.updated_at = datetime.now().isoformat()
        self._save_tasks()
        return True

    def update_task_status(self, task_id: str, new_status: str) -> bool:
        if new_status not in VALID_STATUSES:
            return False
        task = next((t for t in self.tasks if t.id == task_id), None)
        if not task:
            return False
        task.status = new_status
        task.updated_at = datetime.now().isoformat()
        if new_status == "backlog":
            task.sprint_id = None
        self._save_tasks()
        return True

    # --- Queries ---

    def get_current_sprint(self) -> Optional[Sprint]:
        now = datetime.now().isoformat()
        for s in self.sprints:
            if s.status == "active" and s.start_date <= now <= s.end_date:
                return s
        return self.sprints[-1] if self.sprints else None

    def get_backlog(self) -> List[Task]:
        return sorted([t for t in self.tasks if t.status == "backlog"], key=lambda t: t.priority)

    def get_tasks_for_sprint(self, sprint_id: str) -> List[Task]:
        return [t for t in self.tasks if t.sprint_id == sprint_id]

    def calculate_sprint_completion(self, sprint_id: str) -> float:
        sprint_tasks = self.get_tasks_for_sprint(sprint_id)
        if not sprint_tasks:
            return 0.0
        done = sum(1 for t in sprint_tasks if t.status == "done")
        return round(done / len(sprint_tasks) * 100, 1)

    def get_sprint_velocity(self, sprint_id: str) -> float:
        done_tasks = [t for t in self.tasks if t.sprint_id == sprint_id and t.status == "done"]
        return sum(t.estimate_hours for t in done_tasks)

    def get_tasks_completed_since(self, since_iso: str) -> List[Task]:
        return [t for t in self.tasks if t.status == "done" and t.updated_at >= since_iso]

    def get_velocity_trend(self, weeks: int = 4) -> List[Dict]:
        trend = []
        for s in self.sprints[-weeks:]:
            trend.append({
                "sprint": s.name,
                "velocity": self.get_sprint_velocity(s.id),
                "completion": self.calculate_sprint_completion(s.id),
            })
        return trend

    def get_summary_stats(self) -> Dict:
        total = len(self.tasks)
        by_status = {}
        for s in VALID_STATUSES:
            by_status[s] = sum(1 for t in self.tasks if t.status == s)

        current = self.get_current_sprint()
        return {
            "tasks_total": total,
            "tasks_done": by_status.get("done", 0),
            "tasks_in_progress": by_status.get("in_progress", 0),
            "tasks_in_review": by_status.get("review", 0),
            "tasks_backlog": by_status.get("backlog", 0),
            "active_sprint": asdict(current) if current else None,
            "velocity": self.get_sprint_velocity(current.id) if current else 0,
        }

    def prioritize_backlog(self) -> List[Task]:
        backlog = self.get_backlog()
        for i, task in enumerate(backlog):
            task.priority = i + 1
            task.updated_at = datetime.now().isoformat()
        self._save_tasks()
        return backlog
