"""
SAMMS ENTERPRISE SOVEREIGN OPERATING SYSTEM - Base Service
Foundation service class with common business logic patterns.
"""

from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from datetime import datetime
from decimal import Decimal
from typing import (
    Optional, List, Dict, Any, Generic, TypeVar, Union,
    Callable, Awaitable, Protocol
)
from uuid import UUID
import asyncio
import logging
from functools import wraps

from sqlalchemy.ext.asyncio import AsyncSession

from ..repositories.base import BaseRepository
from ..core.exceptions import (
    NotFoundError,
    ValidationError,
    BusinessLogicError,
    PermissionDeniedError,
    ConflictError
)
from ..core.events import EventPublisher
from ..core.cache import CacheManager


logger = logging.getLogger(__name__)


@dataclass
class Result(Generic[TypeVar('T')]):
    """
    Generic result wrapper for service operations.
    Provides success/failure status, data, errors, and metadata.
    """
    success: bool
    data: Optional[Any] = None
    errors: List[str] = field(default_factory=list)
    warnings: List[str] = field(default_factory=list)
    metadata: Dict[str, Any] = field(default_factory=dict)
    
    @classmethod
    def ok(cls, data: Any = None, metadata: Optional[Dict[str, Any]] = None, warnings: Optional[List[str]] = None) -> 'Result':
        """Create a successful result."""
        return cls(
            success=True,
            data=data,
            warnings=warnings or [],
            metadata=metadata or {}
        )
    
    @classmethod
    def fail(cls, errors: Union[str, List[str]], metadata: Optional[Dict[str, Any]] = None) -> 'Result':
        """Create a failed result."""
        error_list = [errors] if isinstance(errors, str) else errors
        return cls(
            success=False,
            errors=error_list,
            metadata=metadata or {}
        )
    
    @classmethod
    def partial(cls, data: Any, warnings: List[str], metadata: Optional[Dict[str, Any]] = None) -> 'Result':
        """Create a partial success result with warnings."""
        return cls(
            success=True,
            data=data,
            warnings=warnings,
            metadata=metadata or {}
        )
    
    def add_error(self, error: str) -> 'Result':
        """Add an error to the result."""
        self.errors.append(error)
        self.success = False
        return self
    
    def add_warning(self, warning: str) -> 'Result':
        """Add a warning to the result."""
        self.warnings.append(warning)
        return self
    
    def merge(self, other: 'Result') -> 'Result':
        """Merge another result into this one."""
        self.errors.extend(other.errors)
        self.warnings.extend(other.warnings)
        self.metadata.update(other.metadata)
        if not other.success:
            self.success = False
        return self


# Type alias for service results
ServiceResult = Result


@dataclass
class PaginationResult(Generic[TypeVar('T')]):
    """
    Result wrapper for paginated data.
    """
    items: List[Any]
    total: int
    page: int
    page_size: int
    total_pages: int
    has_next: bool
    has_prev: bool
    
    @classmethod
    def create(
        cls,
        items: List[Any],
        total: int,
        page: int,
        page_size: int
    ) -> 'PaginationResult':
        """Create a pagination result."""
        total_pages = (total + page_size - 1) // page_size if page_size > 0 else 0
        return cls(
            items=items,
            total=total,
            page=page,
            page_size=page_size,
            total_pages=total_pages,
            has_next=page < total_pages,
            has_prev=page > 1
        )


class ServiceContext:
    """
    Context object passed through service operations.
    Contains user info, company info, and request metadata.
    """
    def __init__(
        self,
        user_id: Optional[UUID] = None,
        company_id: Optional[UUID] = None,
        roles: Optional[List[str]] = None,
        permissions: Optional[List[str]] = None,
        request_id: Optional[str] = None,
        ip_address: Optional[str] = None,
        user_agent: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None
    ):
        self.user_id = user_id
        self.company_id = company_id
        self.roles = roles or []
        self.permissions = permissions or []
        self.request_id = request_id
        self.ip_address = ip_address
        self.user_agent = user_agent
        self.metadata = metadata or {}
        self.created_at = datetime.utcnow()
    
    def has_permission(self, permission: str) -> bool:
        """Check if context has a specific permission."""
        return permission in self.permissions
    
    def has_any_permission(self, permissions: List[str]) -> bool:
        """Check if context has any of the specified permissions."""
        return any(p in self.permissions for p in permissions)
    
    def has_all_permissions(self, permissions: List[str]) -> bool:
        """Check if context has all specified permissions."""
        return all(p in self.permissions for p in permissions)
    
    def has_role(self, role: str) -> bool:
        """Check if context has a specific role."""
        return role in self.roles
    
    def is_authenticated(self) -> bool:
        """Check if context represents an authenticated user."""
        return self.user_id is not None


class BaseService(ABC):
    """
    Base service class providing common business logic patterns.
    
    Features:
    - Repository management
    - Event publishing
    - Caching
    - Logging
    - Transaction management
    - Validation helpers
    """
    
    def __init__(
        self,
        session: AsyncSession,
        cache: Optional[CacheManager] = None,
