"""
Main Gitea client facade.

This provides a clean, organized interface for all Gitea operations,
following the facade pattern to hide complexity and provide a stable API.
"""

from typing import List, Optional, Dict, Any

from .config import GiteaConfig
from .api_client import GiteaApiClient
from .models import Issue, Milestone, Label, IssueCreateData, IssueUpdateData, MilestoneCreateData, LabelCreateData, ProjectState, Priority


class IssuesClient:
    """Client for issue operations."""

    def __init__(self, api_client: GiteaApiClient):
        self._api = api_client

    def get(self, issue_number: int) -> Issue:
        """Get a specific issue by number."""
        return self._api.get_issue(issue_number)

    def list(self, state: str = "all", page: int = 1, per_page: int = 50) -> List[Issue]:
        """List issues with optional filtering."""
        return self._api.list_issues(state, page, per_page)

    def list_open(self) -> List[Issue]:
        """List only open issues."""
        return self._api.list_issues("open")

    def list_closed(self) -> List[Issue]:
        """List only closed issues."""
        return self._api.list_issues("closed")

    def create(self, title: str, body: str = "", **kwargs) -> Issue:
        """Create a new issue."""
        issue_data = IssueCreateData(
            title=title,
            body=body,
            assignees=kwargs.get('assignees', []),
            milestone=kwargs.get('milestone'),
            labels=kwargs.get('labels', [])
        )
        return self._api.create_issue(issue_data)

    def update(self, issue_number: int, **kwargs) -> Issue:
        """Update an existing issue."""
        update_data = IssueUpdateData(
            title=kwargs.get('title'),
            body=kwargs.get('body'),
            state=kwargs.get('state'),
            assignees=kwargs.get('assignees'),
            milestone=kwargs.get('milestone'),
            labels=kwargs.get('labels')
        )
        return self._api.update_issue(issue_number, update_data)

    def close(self, issue_number: int) -> Issue:
        """Close an issue."""
        return self.update(issue_number, state="closed")

    def reopen(self, issue_number: int) -> Issue:
        """Reopen an issue."""
        return self.update(issue_number, state="open")

    def add_labels(self, issue_number: int, labels: List[str]) -> Issue:
        """Add labels to an issue."""
        issue = self.get(issue_number)
        existing_labels = [label.name for label in issue.labels]
        new_labels = list(set(existing_labels + labels))
        return self.update(issue_number, labels=new_labels)

    def remove_labels(self, issue_number: int, labels: List[str]) -> Issue:
        """Remove labels from an issue."""
        issue = self.get(issue_number)
        existing_labels = [label.name for label in issue.labels]
        new_labels = [label for label in existing_labels if label not in labels]
        return self.update(issue_number, labels=new_labels)

    def set_priority(self, issue_number: int, priority: Priority) -> Issue:
        """Set issue priority."""
        issue = self.get(issue_number)
        labels = [label.name for label in issue.labels if not label.name.startswith('priority:')]
        labels.append(priority.value)
        return self.update(issue_number, labels=labels)

    def set_status(self, issue_number: int, status: ProjectState) -> Issue:
        """Set issue status."""
        issue = self.get(issue_number)
        labels = [label.name for label in issue.labels if not label.name.startswith('status:')]
        labels.append(status.value)
        return self.update(issue_number, labels=labels)

    def assign_to_milestone(self, issue_number: int, milestone_id: int) -> Issue:
        """Assign issue to a milestone."""
        return self.update(issue_number, milestone=milestone_id)

    def remove_from_milestone(self, issue_number: int) -> Issue:
        """Remove issue from milestone."""
        return self.update(issue_number, milestone=None)

    def set_labels(self, issue_number: int, labels: List[str]) -> Issue:
        """Replace all labels on an issue."""
        return self.update(issue_number, labels=labels)

    def update_title(self, issue_number: int, title: str) -> Issue:
        """Update only the title of an issue."""
        return self.update(issue_number, title=title)

    def update_body(self, issue_number: int, body: str) -> Issue:
        """Update only the body of an issue."""
        return self.update(issue_number, body=body)

    def to_dict(self, issue: Issue) -> Dict[str, Any]:
        """Convert Issue object to dictionary format for backward 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': {
                'id': issue.milestone.id,
                'title': issue.milestone.title
            } if issue.milestone else None
        }


class MilestonesClient:
    """Client for milestone operations."""

    def __init__(self, api_client: GiteaApiClient):
        self._api = api_client

    def list(self, state: str = "all") -> List[Milestone]:
        """List milestones."""
        return self._api.list_milestones(state)

    def list_open(self) -> List[Milestone]:
        """List open milestones."""
        return self._api.list_milestones("open")

    def list_closed(self) -> List[Milestone]:
        """List closed milestones."""
        return self._api.list_milestones("closed")

    def create(self, title: str, description: str = "", due_on: str = None) -> Milestone:
        """Create a new milestone."""
        milestone_data = MilestoneCreateData(
            title=title,
            description=description,
            due_on=due_on
        )
        return self._api.create_milestone(milestone_data)


class LabelsClient:
    """Client for label operations."""

    def __init__(self, api_client: GiteaApiClient):
        self._api = api_client

    def list(self) -> List[Label]:
        """List all labels."""
        return self._api.list_labels()

    def create(self, name: str, color: str, description: str = "") -> Label:
        """Create a new label."""
        label_data = LabelCreateData(
            name=name,
            color=color,
            description=description
        )
        return self._api.create_label(label_data)

    def ensure_project_labels(self) -> None:
        """Ensure all standard project management labels exist."""
        existing_labels = [label.name for label in self.list()]

        # Define standard project labels
        standard_labels = [
            ("status:todo", "d73a4a", "Ready to work on"),
            ("status:active", "0075ca", "Currently being worked on"),
            ("status:review", "fbca04", "Ready for review"),
            ("status:done", "0e8a16", "Completed work"),
            ("status:blocked", "b60205", "Blocked by dependencies"),
            ("priority:low", "c5def5", "Low priority"),
            ("priority:medium", "a2eeef", "Medium priority"),
            ("priority:high", "fef2c0", "High priority"),
            ("priority:critical", "d93f0b", "Critical priority"),
        ]

        for name, color, description in standard_labels:
            if name not in existing_labels:
                self.create(name, color, description)


class GiteaClient:
    """Main Gitea client facade."""

    def __init__(self, config: Optional[GiteaConfig] = None):
        """Initialize Gitea client.

        Args:
            config: GiteaConfig instance. If None, auto-detects from git repository.
        """
        if config is None:
            try:
                config = GiteaConfig.from_git_repository()
            except Exception:
                # Fallback to environment-based config if git detection fails
                config = GiteaConfig.from_environment()
            config.validate()

        self.config = config
        self._api = GiteaApiClient(config)

        # Initialize sub-clients
        self.issues = IssuesClient(self._api)
        self.milestones = MilestonesClient(self._api)
        self.labels = LabelsClient(self._api)

    @classmethod
    def from_tddai_config(cls, tddai_config) -> 'GiteaClient':
        """Create client from legacy TddaiConfig for backwards compatibility."""
        gitea_config = GiteaConfig.from_tddai_config(tddai_config)
        return cls(gitea_config)

    def setup_project_management(self) -> None:
        """Setup standard project management labels and structure."""
        self.labels.ensure_project_labels()