"""Questionnaire operations for Archer REST API."""

import logging
from typing import List, Dict, Any, Optional, Union

from ..models.questionnaire import Questionnaire, QuestionnaireRule
from .base import BaseAPI


logger = logging.getLogger(__name__)


class QuestionnairesAPI(BaseAPI):
    """
    API client for Archer questionnaire operations.
    
    Questionnaires are similar to applications but include cross-reference
    fields that link to target applications for creating records.
    """
    
    def get_all(self, as_model: bool = False) -> Union[List[Dict[str, Any]], List[Questionnaire]]:
        """
        Get all questionnaires.
        
        Args:
            as_model: If True, return as list of Questionnaire models
            
        Returns:
            List of questionnaires as dicts or Questionnaire models
            
        Example:
            >>> # As dictionaries
            >>> questionnaires = client.rest.questionnaires.get_all()
            >>> 
            >>> # As models with validation and helper methods
            >>> questionnaires = client.rest.questionnaires.get_all(as_model=True)
            >>> for q in questionnaires:
            ...     print(f"{q.Name} -> {q.TargetApplicationName}")
        """
        url = f"{self.base_url}/platformapi/core/system/questionnaire"
        response = self._make_request("POST", url, headers={"X-Http-Method-Override": "GET"})
        data = response.json()
        
        if as_model:
            return [Questionnaire(**q) for q in data]
        return data
    
    def get(
        self,
        questionnaire_id: int,
        as_model: bool = False,
        include_rules: bool = False
    ) -> Union[Dict[str, Any], Questionnaire]:
        """
        Get a specific questionnaire by ID.
        
        Args:
            questionnaire_id: Questionnaire ID
            as_model: If True, return as Questionnaire model
            include_rules: If True and as_model=True, fetch and include rules
            
        Returns:
            Questionnaire data as dict or Questionnaire model
            
        Example:
            >>> # Get questionnaire with rules
            >>> q = client.rest.questionnaires.get(
            ...     questionnaire_id=100,
            ...     as_model=True,
            ...     include_rules=True
            ... )
            >>> 
            >>> print(f"Questionnaire: {q.Name}")
            >>> print(f"Target Application: {q.TargetApplicationName}")
            >>> print(f"Rules: {len(q.rules)}")
            >>> 
            >>> # Find rules for a specific level
            >>> level_rules = q.get_rules_by_level(75)
        """
        url = f"{self.base_url}/platformapi/core/system/questionnaire/{questionnaire_id}"
        response = self._make_request("POST", url, headers={"X-Http-Method-Override": "GET"})
        data = response.json()
        
        if as_model:
            questionnaire = Questionnaire(**data)
            
            # Optionally fetch and attach rules
            if include_rules:
                # Get rules by questionnaire's target level if available
                if questionnaire.TargetApplicationId:
                    rules_data = self.get_rules_by_level(questionnaire.TargetApplicationId)
                    questionnaire.rules = [QuestionnaireRule(**r) for r in rules_data]
            
            return questionnaire
        
        return data
    
    def get_rule(
        self,
        rule_id: int,
        as_model: bool = False
    ) -> Union[Dict[str, Any], QuestionnaireRule]:
        """
        Get a specific questionnaire rule by ID.
        
        Args:
            rule_id: Questionnaire rule ID
            as_model: If True, return as QuestionnaireRule model
            
        Returns:
            Rule data as dict or QuestionnaireRule model
            
        Example:
            >>> rule = client.rest.questionnaires.get_rule(501, as_model=True)
            >>> print(f"Rule: {rule.Name}")
            >>> print(f"Questionnaire ID: {rule.QuestionnaireId}")
        """
        url = f"{self.base_url}/platformapi/core/system/questionnairerule/{rule_id}"
        response = self._make_request("POST", url, headers={"X-Http-Method-Override": "GET"})
        data = response.json()
        
        if as_model:
            return QuestionnaireRule(**data)
        return data
    
    def get_rules_by_level(
        self,
        level_id: int,
        as_model: bool = False
    ) -> Union[List[Dict[str, Any]], List[QuestionnaireRule]]:
        """
        Get all questionnaire rules for a specific level/application.
        
        Args:
            level_id: Level/Application ID
            as_model: If True, return as list of QuestionnaireRule models
            
        Returns:
            List of rules as dicts or QuestionnaireRule models
            
        Example:
            >>> # Get all rules for an application
            >>> rules = client.rest.questionnaires.get_rules_by_level(
            ...     level_id=75,
            ...     as_model=True
            ... )
            >>> 
            >>> for rule in rules:
            ...     print(f"Rule: {rule.Name} (ID: {rule.Id})")
        """
        url = f"{self.base_url}/platformapi/core/system/questionnairerule/level/{level_id}"
        response = self._make_request("POST", url, headers={"X-Http-Method-Override": "GET"})
        data = response.json()
        
        if as_model:
            return [QuestionnaireRule(**r) for r in data]
        return data
    
    def find_by_target_application(
        self,
        application_id: int,
        as_model: bool = False
    ) -> Union[List[Dict[str, Any]], List[Questionnaire]]:
        """
        Find all questionnaires that target a specific application.
        
        This is a helper method that filters questionnaires by their
        target application ID.
        
        Args:
            application_id: Target application ID
            as_model: If True, return as list of Questionnaire models
            
        Returns:
            List of questionnaires targeting the application
            
        Example:
            >>> # Find all questionnaires for Security Incidents app
            >>> questionnaires = client.rest.questionnaires.find_by_target_application(
            ...     application_id=75,
            ...     as_model=True
            ... )
            >>> 
            >>> for q in questionnaires:
            ...     print(f"Questionnaire: {q.Name}")
        """
        all_questionnaires = self.get_all(as_model=True)
        
        # Filter by target application
        filtered = [
            q for q in all_questionnaires
            if q.TargetApplicationId == application_id
        ]
        
        if not as_model:
            # Convert back to dicts if needed
            return [q.model_dump() for q in filtered]
        
        return filtered
