"""
Project management functionality using the Gitea facade.

This module now acts as an adapter to the new gitea package,
maintaining backwards compatibility while using the cleaner API.
"""

import os
from typing import Dict, Any, List, Optional

from gitea import GiteaClient, GiteaConfig
from gitea.models import ProjectState, Priority, Milestone as GiteaMilestone, Label as GiteaLabel
from gitea.exceptions import GiteaError, GiteaNotFoundError, GiteaAuthError, GiteaApiError
from .config import get_config
from .exceptions import IssueError

# Re-export for backwards compatibility
Milestone = GiteaMilestone
Label = GiteaLabel


class ProjectManager:
    """Manages project organization using the Gitea facade."""

    def __init__(self, config=None, auth_token=None):
        self.config = config or get_config()
        self.auth_token = auth_token or os.getenv('GITEA_API_TOKEN')

        # Create Gitea client from tddai config
        gitea_config = GiteaConfig.from_tddai_config(self.config)
        if self.auth_token:
            gitea_config.auth_token = self.auth_token
        self.gitea_client = GiteaClient(gitea_config)

    def _make_api_call(self, method: str, url: str, data: Dict[str, Any] = None) -> Dict[str, Any]:
        """Make authenticated API call to Gitea (kept for backwards compatibility).

        Args:
            method: HTTP method (GET, POST, etc.)
            url: API endpoint URL
            data: Optional request data

        Raises:
            IssueError: When API call fails (with specific context)
        """
        # This method is kept for backwards compatibility but now delegates to the gitea client
        # For new code, use the gitea_client directly
        try:
            if method == 'GET' and 'issues' in url and url.endswith('/issues'):
                issues = self.gitea_client.issues.list()
                return [self._issue_to_dict(issue) for issue in issues]
            elif method == 'GET' and '/issues/' in url and not url.endswith('/labels'):
                issue_number = int(url.split('/issues/')[-1])
                issue = self.gitea_client.issues.get(issue_number)
                return self._issue_to_dict(issue)
            else:
                raise IssueError(f"Legacy API call not supported: {method} {url}")
        except GiteaNotFoundError as e:
            raise IssueError(f"Resource not found for {method} {url}") from e
        except GiteaAuthError as e:
            raise IssueError(f"Authentication failed for {method} {url}") from e
        except GiteaApiError as e:
            raise IssueError(f"API error for {method} {url}: {e}") from e
        except GiteaError as e:
            raise IssueError(f"Gitea error for {method} {url}: {e}") from e
        except (ValueError, IndexError) as e:
            raise IssueError(f"Invalid URL format for {method} {url}") from e

    def _issue_to_dict(self, issue) -> Dict[str, Any]:
        """Convert Issue object to dict for backwards compatibility."""
        return {
            'number': issue.number,
            'title': issue.title,
            'body': issue.body,
            'state': issue.state,
            'html_url': issue.html_url,
            'created_at': issue.created_at.isoformat(),
            'updated_at': issue.updated_at.isoformat(),
            'assignee': {'login': issue.assignee.login} if issue.assignee else None,
            'labels': [{'name': label.name, 'color': label.color} for label in issue.labels]
        }

    # Milestone Management (Projects)

    def create_milestone(self, title: str, description: str = "", due_date: Optional[str] = None) -> Milestone:
        """Create a new milestone (project)."""
        try:
            return self.gitea_client.milestones.create(title, description, due_date)
        except Exception as e:
            raise IssueError(f"Failed to create milestone: {e}")

    def list_milestones(self, state: str = "open") -> List[Milestone]:
        """List all milestones (projects)."""
        try:
            if state == "all":
                return self.gitea_client.milestones.list()
            elif state == "open":
                return self.gitea_client.milestones.list_open()
            elif state == "closed":
                return self.gitea_client.milestones.list_closed()
            else:
                return self.gitea_client.milestones.list(state)
        except Exception as e:
            raise IssueError(f"Failed to list milestones: {e}")

    def update_milestone(self, milestone_id: int, **kwargs) -> Milestone:
        """Update milestone details."""
        url = f"{self.config.gitea_url}/api/v1/repos/{self.config.repo_owner}/{self.config.repo_name}/milestones/{milestone_id}"

        # Only include fields that can be updated
        valid_fields = ['title', 'description', 'state', 'due_on']
        data = {k: v for k, v in kwargs.items() if k in valid_fields}

        response = self._make_api_call('PATCH', url, data)

        return Milestone(
            id=response['id'],
            title=response['title'],
            description=response.get('description', ''),
            state=response['state'],
            open_issues=response['open_issues'],
            closed_issues=response['closed_issues'],
            due_on=response.get('due_on')
        )

    def close_milestone(self, milestone_id: int) -> Milestone:
        """Close a milestone (complete project)."""
        return self.update_milestone(milestone_id, state='closed')

    # Label Management (States & Priority)

    def create_label(self, name: str, color: str, description: str = "") -> Label:
        """Create a new label."""
        url = f"{self.config.gitea_url}/api/v1/repos/{self.config.repo_owner}/{self.config.repo_name}/labels"

        data = {
            'name': name,
            'color': color,
            'description': description
        }

        response = self._make_api_call('POST', url, data)

        return Label(
            id=response['id'],
            name=response['name'],
            color=response['color'],
            description=response.get('description', '')
        )

    def list_labels(self) -> List[Label]:
        """List all repository labels."""
        url = f"{self.config.gitea_url}/api/v1/repos/{self.config.repo_owner}/{self.config.repo_name}/labels"

        response = self._make_api_call('GET', url)

        return [
            Label(
                id=l['id'],
                name=l['name'],
                color=l['color'],
                description=l.get('description', '')
            )
            for l in response
        ]

    def ensure_project_labels(self) -> None:
        """Ensure all required project management labels exist."""
        try:
            self.gitea_client.labels.ensure_project_labels()
        except Exception as e:
            raise IssueError(f"Failed to ensure project labels: {e}")

    def list_labels(self) -> List[Label]:
        """List all repository labels."""
        try:
            return self.gitea_client.labels.list()
        except Exception as e:
            raise IssueError(f"Failed to list labels: {e}")

    def create_label(self, name: str, color: str, description: str = "") -> Label:
        """Create a new label."""
        try:
            return self.gitea_client.labels.create(name, color, description)
        except Exception as e:
            raise IssueError(f"Failed to create label: {e}")

    # Project Management Operations

    def assign_issue_to_milestone(self, issue_number: int, milestone_id: int) -> Dict[str, Any]:
        """Assign issue to a milestone (project)."""
        url = f"{self.config.issues_api_url}/{issue_number}"

        data = {'milestone': milestone_id}
        return self._make_api_call('PATCH', url, data)

    def set_issue_state(self, issue_number: int, state: ProjectState) -> Dict[str, Any]:
        """Set issue project state using labels."""
        try:
            issue = self.gitea_client.issues.set_status(issue_number, state)
            return self._issue_to_dict(issue)
        except Exception as e:
            raise IssueError(f"Failed to set issue state: {e}")

    def set_issue_priority(self, issue_number: int, priority: Priority) -> Dict[str, Any]:
        """Set issue priority using labels."""
        try:
            issue = self.gitea_client.issues.set_priority(issue_number, priority)
            return self._issue_to_dict(issue)
        except Exception as e:
            raise IssueError(f"Failed to set issue priority: {e}")

    def move_issue_to_done(self, issue_number: int) -> Dict[str, Any]:
        """Move issue to done state and close it."""
        try:
            # Set state to done
            self.set_issue_state(issue_number, ProjectState.DONE)

            # Close the issue
            issue = self.gitea_client.issues.close(issue_number)
            return self._issue_to_dict(issue)
        except Exception as e:
            raise IssueError(f"Failed to move issue to done: {e}")

    def get_project_overview(self) -> Dict[str, Any]:
        """Get overview of project status."""
        milestones = self.list_milestones("all")
        labels = self.list_labels()

        # Count issues by state
        state_counts = {}
        for state in ProjectState:
            state_counts[state.value] = 0

        # This would require fetching all issues to count by labels
        # For now, return milestone overview

        return {
            'milestones': len(milestones),
            'active_projects': len([m for m in milestones if m.state == 'open']),
            'completed_projects': len([m for m in milestones if m.state == 'closed']),
            'total_labels': len(labels),
            'project_management_ready': len([l for l in labels if l.name.startswith('status:')]) > 0
        }