"""
Thread (comment) operations for tasks
"""

from typing import Dict, Any, List, Optional
from ..models import Comment, TallyfyError
from ..validation import validate_id


class ThreadManager:
    """Handles reading and writing task comments (threads)"""

    def __init__(self, sdk):
        self.sdk = sdk

    def _validate(self, **kwargs) -> None:
        for name, value in kwargs.items():
            validate_id(value, name)

    def _handle_api_error(self, error: Exception, operation: str, **context) -> None:
        context_str = ", ".join(f"{k}={v}" for k, v in context.items())
        msg = f"Failed to {operation}"
        if context_str:
            msg += f" ({context_str})"
        msg += f": {error}"
        self.sdk.logger.error(msg)
        if isinstance(error, TallyfyError):
            raise error
        raise TallyfyError(msg)

    def add_task_comment(self, org_id: str, task_id: str, content: str,
                         state: Optional[str] = None,
                         label: Optional[str] = None) -> Comment:
        """
        Post a new comment on a task.

        Args:
            org_id: Organization ID
            task_id: Task ID to comment on
            content: Comment text (required)
            state: Visibility — "open" | "hide-for-guests" | "collapsed" (default: "open")
            label: Label type — "comment" | "problem" | "resolve" | "improvement" | "advice"

        Returns:
            Comment object

        Raises:
            TallyfyError: If the request fails
            ValueError: If required parameters are missing
        """
        self._validate(org_id=org_id, task_id=task_id)

        if not content or not isinstance(content, str):
            raise ValueError("content must be a non-empty string")

        try:
            endpoint = f"organizations/{org_id}/tasks/{task_id}/comment"

            body: Dict[str, Any] = {"content": content}
            if state is not None:
                body["state"] = state
            if label is not None:
                body["label"] = label

            response_data = self.sdk._make_request('POST', endpoint, data=body)

            if isinstance(response_data, dict) and 'data' in response_data:
                data = response_data['data']
                if isinstance(data, dict):
                    return Comment.from_dict(data)

            if isinstance(response_data, dict):
                return Comment.from_dict(response_data)

            raise TallyfyError("Unexpected response format for add_task_comment")

        except TallyfyError:
            raise
        except Exception as e:
            self._handle_api_error(e, "add task comment", org_id=org_id, task_id=task_id)

    def get_task_comments(self, org_id: str, run_id: str, task_id: str) -> List[Comment]:
        """
        Get all comments on a specific task.

        Fetches the task with ``?with=threads`` and extracts the nested
        ``threads.data`` list from the response.

        Args:
            org_id: Organization ID
            run_id: Run (process) ID
            task_id: Task ID

        Returns:
            List of Comment objects

        Raises:
            TallyfyError: If the request fails
            ValueError: If required parameters are missing
        """
        self._validate(org_id=org_id, run_id=run_id, task_id=task_id)

        try:
            endpoint = f"organizations/{org_id}/runs/{run_id}/tasks/{task_id}"
            params = {"with": "threads"}

            response_data = self.sdk._make_request('GET', endpoint, params=params)

            # Response: {"data": {"threads": {"data": [...]}, ...}}
            task_data = response_data.get('data', {}) if isinstance(response_data, dict) else {}
            threads_wrapper = task_data.get('threads', {})
            items = threads_wrapper.get('data', []) if isinstance(threads_wrapper, dict) else []

            return [Comment.from_dict(item) for item in items if isinstance(item, dict)]

        except TallyfyError:
            raise
        except Exception as e:
            self._handle_api_error(e, "get task comments",
                                   org_id=org_id, run_id=run_id, task_id=task_id)

    def update_task_comment(self, org_id: str, task_id: str, comment_id: str,
                            content: str,
                            state: Optional[str] = None,
                            label: Optional[str] = None) -> Comment:
        """
        Update an existing comment on a task.

        Args:
            org_id: Organization ID
            task_id: Task ID
            comment_id: Comment ID to update
            content: New comment text (required)
            state: Visibility — "open" | "hide-for-guests" | "collapsed"
            label: Label type — "comment" | "problem" | "resolve" | "improvement" | "advice"

        Returns:
            Updated Comment object

        Raises:
            TallyfyError: If the request fails
            ValueError: If required parameters are missing
        """
        self._validate(org_id=org_id, task_id=task_id, comment_id=comment_id)

        if not content or not isinstance(content, str):
            raise ValueError("content must be a non-empty string")

        try:
            endpoint = f"organizations/{org_id}/tasks/{task_id}/comment/{comment_id}"

            body: Dict[str, Any] = {"content": content}
            if state is not None:
                body["state"] = state
            if label is not None:
                body["label"] = label

            response_data = self.sdk._make_request('PUT', endpoint, data=body)

            if isinstance(response_data, dict) and 'data' in response_data:
                data = response_data['data']
                if isinstance(data, dict):
                    return Comment.from_dict(data)

            if isinstance(response_data, dict):
                return Comment.from_dict(response_data)

            raise TallyfyError("Unexpected response format for update_task_comment")

        except TallyfyError:
            raise
        except Exception as e:
            self._handle_api_error(e, "update task comment",
                                   org_id=org_id, task_id=task_id, comment_id=comment_id)

    def report_task_issue(self, org_id: str, task_id: str, content: str) -> Comment:
        """
        Report an issue (problem) on a task.

        Args:
            org_id: Organization ID
            task_id: Task ID to report issue on
            content: Issue description text (required)

        Returns:
            Comment object representing the issue

        Raises:
            TallyfyError: If the request fails
            ValueError: If required parameters are missing
        """
        self._validate(org_id=org_id, task_id=task_id)

        if not content or not isinstance(content, str):
            raise ValueError("content must be a non-empty string")

        try:
            endpoint = f"organizations/{org_id}/tasks/{task_id}/problem"
            body: Dict[str, Any] = {"content": content}

            response_data = self.sdk._make_request('POST', endpoint, data=body)

            if isinstance(response_data, dict) and 'data' in response_data:
                data = response_data['data']
                if isinstance(data, dict):
                    return Comment.from_dict(data)

            if isinstance(response_data, dict):
                return Comment.from_dict(response_data)

            raise TallyfyError("Unexpected response format for report_task_issue")

        except TallyfyError:
            raise
        except Exception as e:
            self._handle_api_error(e, "report task issue", org_id=org_id, task_id=task_id)

    def resolve_task_issues(self, org_id: str, task_id: str, thread_id: str) -> bool:
        """
        Resolve an open issue on a task.

        Args:
            org_id: Organization ID
            task_id: Task ID to resolve issues on
            thread_id: Issue comment ID to resolve (returned by report_task_issue)

        Returns:
            True if resolved successfully

        Raises:
            TallyfyError: If the request fails
        """
        self._validate(org_id=org_id, task_id=task_id, thread_id=thread_id)

        try:
            endpoint = f"organizations/{org_id}/tasks/{task_id}/resolved-threads"
            body = {"thread_id": thread_id, "content": "Resolved"}
            self.sdk._make_request('POST', endpoint, data=body)
            return True

        except TallyfyError:
            raise
        except Exception as e:
            self._handle_api_error(e, "resolve task issues", org_id=org_id, task_id=task_id)

    def delete_task_comment(self, org_id: str, task_id: str, comment_id: str) -> bool:
        """
        Delete a comment on a task.

        Args:
            org_id: Organization ID
            task_id: Task ID
            comment_id: Comment ID to delete

        Returns:
            True if deleted successfully

        Raises:
            TallyfyError: If the request fails
            ValueError: If required parameters are missing
        """
        self._validate(org_id=org_id, task_id=task_id, comment_id=comment_id)

        try:
            endpoint = f"organizations/{org_id}/tasks/{task_id}/comment/{comment_id}"
            self.sdk._make_request('DELETE', endpoint)
            return True

        except TallyfyError:
            raise
        except Exception as e:
            self._handle_api_error(e, "delete task comment",
                                   org_id=org_id, task_id=task_id, comment_id=comment_id)
