"""
Guest CRUD operations
"""

from typing import Dict, Any, Optional
from .base import UserManagerBase
from ..models import Guest, TasksList, TallyfyError


class GuestOperations(UserManagerBase):
    """Handles guest CRUD operations"""

    def create_guest(self, org_id: str, email: str, first_name: str,
                     last_name: str, phone: Optional[str] = None,
                     company_name: Optional[str] = None) -> Guest:
        """
        Create a new guest in the organization.

        Args:
            org_id: Organization ID
            email: Guest email address (required)
            first_name: Guest first name (required)
            last_name: Guest last name (required)
            phone: Guest phone number
            company_name: Guest company name

        Returns:
            Created Guest object

        Raises:
            TallyfyError: If the request fails
            ValueError: If required parameters are missing or invalid
        """
        self._validate_org_id(org_id)
        self._validate_email(email)
        self._validate_name(first_name, "First name")
        self._validate_name(last_name, "Last name")

        try:
            endpoint = f"organizations/{org_id}/guests"
            body: Dict[str, Any] = {
                "email": email,
                "first_name": first_name.strip(),
                "last_name": last_name.strip()
            }

            if phone is not None:
                body["phone"] = phone
            if company_name is not None:
                body["company_name"] = company_name

            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 Guest.from_dict(data)

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

            raise TallyfyError("Unexpected response format for create_guest")

        except TallyfyError:
            raise
        except Exception as e:
            self._handle_api_error(e, "create guest", org_id=org_id, email=email)

    def get_guest(self, org_id: str, email: str) -> Guest:
        """
        Get a single guest by email.

        Args:
            org_id: Organization ID
            email: Guest email address

        Returns:
            Guest object

        Raises:
            TallyfyError: If the request fails
        """
        self._validate_org_id(org_id)
        self._validate_email(email)

        try:
            endpoint = f"organizations/{org_id}/guests/{email}"
            response_data = self.sdk._make_request('GET', endpoint)

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

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

            raise TallyfyError("Unexpected response format for get_guest")

        except TallyfyError:
            raise
        except Exception as e:
            self._handle_api_error(e, "get guest", org_id=org_id, email=email)

    def update_guest(self, org_id: str, email: str,
                     first_name: Optional[str] = None,
                     last_name: Optional[str] = None,
                     phone: Optional[str] = None,
                     company_name: Optional[str] = None) -> Guest:
        """
        Update a guest's profile.

        Args:
            org_id: Organization ID
            email: Guest email address
            first_name: New first name
            last_name: New last name
            phone: New phone number
            company_name: New company name

        Returns:
            Updated Guest object

        Raises:
            TallyfyError: If the request fails
        """
        self._validate_org_id(org_id)
        self._validate_email(email)

        try:
            endpoint = f"organizations/{org_id}/guests/{email}"
            body: Dict[str, Any] = {}

            if first_name is not None:
                body["first_name"] = first_name.strip()
            if last_name is not None:
                body["last_name"] = last_name.strip()
            if phone is not None:
                body["phone"] = phone
            if company_name is not None:
                body["company_name"] = company_name

            if not body:
                raise ValueError("At least one field must be provided for update")

            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 Guest.from_dict(data)

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

            raise TallyfyError("Unexpected response format for update_guest")

        except TallyfyError:
            raise
        except Exception as e:
            self._handle_api_error(e, "update guest", org_id=org_id, email=email)

    def disable_guest(self, org_id: str, email: str) -> bool:
        """
        Disable a guest in the organization.

        Args:
            org_id: Organization ID
            email: Guest email address

        Returns:
            True if disabled successfully

        Raises:
            TallyfyError: If the request fails
        """
        self._validate_org_id(org_id)
        self._validate_email(email)

        try:
            endpoint = f"organizations/{org_id}/guests/{email}/disable"
            self.sdk._make_request('DELETE', endpoint)
            return True

        except TallyfyError:
            raise
        except Exception as e:
            self._handle_api_error(e, "disable guest", org_id=org_id, email=email)

    def enable_guest(self, org_id: str, email: str) -> bool:
        """
        Re-enable a previously disabled guest.

        Args:
            org_id: Organization ID
            email: Guest email address

        Returns:
            True if enabled successfully

        Raises:
            TallyfyError: If the request fails
        """
        self._validate_org_id(org_id)
        self._validate_email(email)

        try:
            endpoint = f"organizations/{org_id}/guests/{email}/enable"
            self.sdk._make_request('PUT', endpoint)
            return True

        except TallyfyError:
            raise
        except Exception as e:
            self._handle_api_error(e, "enable guest", org_id=org_id, email=email)

    def get_guest_tasks(
        self, org_id: str, guest_id: str,
        status: Optional[str] = None,
        q: Optional[str] = None,
        page: Optional[int] = None,
        per_page: Optional[int] = None,
        without_pagination: Optional[bool] = None,
        with_: Optional[str] = None,
        sort_by: Optional[str] = None,
        sort: Optional[str] = None,
        deadline_on: Optional[str] = None,
        deadline_before: Optional[str] = None,
        deadline_after: Optional[str] = None,
        deadline_start_range: Optional[str] = None,
        deadline_end_range: Optional[str] = None,
    ) -> TasksList:
        """
        Get tasks assigned to a specific guest.

        The guest_id can be obtained from the Guest object's `guest_id`
        property (extracted from the `link` field) or passed directly.

        Args:
            org_id: Organization ID
            guest_id: Guest ID (e.g. from Guest.guest_id or Guest.link)
            status: Filter by status ('active' or 'all', default: 'active')
            q: Search query across task and step names
            page: Page number for pagination
            per_page: Results per page (default: 10)
            without_pagination: Return all results without pagination
            with_: Comma-separated includes. Valid values:
                threads, comments, assets, guest_watchers
            sort_by: Field to sort by (prefix with '-' for DESC)
            sort: Alternative sort parameter
            deadline_on: Exact deadline date (YYYY-MM-DD)
            deadline_before: Tasks with deadline before this date
            deadline_after: Tasks with deadline after this date
            deadline_start_range: Start of deadline range (inclusive)
            deadline_end_range: End of deadline range (inclusive)

        Returns:
            TasksList with guest's tasks and pagination metadata

        Raises:
            TallyfyError: If the request fails
            ValueError: If guest_id is empty
        """
        self._validate_org_id(org_id)
        if not guest_id or not isinstance(guest_id, str) or not guest_id.strip():
            raise ValueError("Guest ID must be a non-empty string")

        try:
            endpoint = f"organizations/{org_id}/guests/{guest_id}/tasks"
            params = self._build_query_params(
                status=status,
                q=q,
                page=page,
                per_page=per_page,
                without_pagination=without_pagination,
                with_=with_,
                sort_by=sort_by,
                sort=sort,
                deadline_on=deadline_on,
                deadline_before=deadline_before,
                deadline_after=deadline_after,
                deadline_start_range=deadline_start_range,
                deadline_end_range=deadline_end_range,
            )
            response_data = self.sdk._make_request('GET', endpoint, params=params)
            return TasksList.from_dict(response_data)

        except TallyfyError:
            raise
        except Exception as e:
            self._handle_api_error(e, "get guest tasks", org_id=org_id,
                                   guest_id=guest_id)
