"""Application operations for Archer REST API with model support."""

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

from ..models.application import Application, FieldDefinition
from .base import BaseAPI


logger = logging.getLogger(__name__)


class ApplicationsAPI(BaseAPI):
    """API client for Archer application operations."""
    
    def get_all(self, as_model: bool = False) -> Union[List[Dict[str, Any]], List[Application]]:
        """Get all applications."""
        url = f"{self.base_url}/platformapi/core/system/application"
        response = self._make_request("GET", url)
        data = response.json()
        
        # Extract from RequestedObject if wrapped
        if isinstance(data, dict) and 'RequestedObject' in data:
            data = data['RequestedObject']
        
        if as_model:
            # Handle both list and single object
            if isinstance(data, list):
                return [Application(**app) for app in data]
            else:
                return [Application(**data)]
        return data
    
    def get(
        self,
        application_id: int,
        as_model: bool = False,
        include_fields: bool = False
    ) -> Union[Dict[str, Any], Application]:
        """
        Get a specific application.
        
        Args:
            application_id: Application ID
            as_model: If True, return as Application model
            include_fields: If True and as_model=True, fetch and include field definitions
            
        Returns:
            Application data as dict or Application model
            
        Example:
            >>> # Method 1: Get as dictionary (traditional)
            >>> app_data = client.rest.applications.get(application_id=191)
            >>> print(app_data)
            >>> 
            >>> # Method 2: Get as model with validation
            >>> app = client.rest.applications.get(application_id=191, as_model=True)
            >>> print(f"App: {app.Name} (ID: {app.Id})")
            >>> 
            >>> # Method 3: Get with fields included
            >>> app = client.rest.applications.get(
            ...     application_id=191,
            ...     as_model=True,
            ...     include_fields=True
            ... )
            >>> for field in app.fields:
            ...     print(f"{field.Name}: {field.type_name}")
        """
        url = f"{self.base_url}/platformapi/core/system/application/{application_id}"
        response = self._make_request("GET", url)
        data = response.json()
        
        # ✅ KEY FIX: Extract from RequestedObject wrapper
        if isinstance(data, dict) and 'RequestedObject' in data:
            data = data['RequestedObject']
        
        if as_model:
            app = Application(**data)
            
            # Optionally fetch and attach field definitions
            if include_fields:
                fields_data = self.get_fields(application_id)
                app.fields = [FieldDefinition(**f) for f in fields_data]
            
            return app
        
        return data
    
    def get_fields(
        self,
        application_id: int,
        as_model: bool = False
    ) -> Union[List[Dict[str, Any]], List[FieldDefinition]]:
        """
        Get fields for an application.
        
        Args:
            application_id: Application ID
            as_model: If True, return as list of FieldDefinition models
            
        Returns:
            List of field definitions
        """
        url = f"{self.base_url}/platformapi/core/system/fielddefinition/application/{application_id}"
        response = self._make_request("GET", url)
        data = response.json()
        
        # Extract from RequestedObject if wrapped
        if isinstance(data, dict) and 'RequestedObject' in data:
            data = data['RequestedObject']
        
        # Ensure data is a list
        if not isinstance(data, list):
            data = [data] if data else []
        
        if as_model:
            return [FieldDefinition(**f) for f in data]
        return data