from datetime import datetime
from typing import Any, Dict, List, Optional, Sequence

from fideslang.models import PrivacyDeclaration, System
from fideslang.validation import FidesKey
from pydantic import ConfigDict, Field
from pydantic.main import BaseModel

from fides.api.schemas.connection_configuration.connection_config import (
    ConnectionConfigurationResponse,
)
from fides.api.schemas.user import UserResponse


class PrivacyDeclarationResponse(PrivacyDeclaration):
    """Extension of base pydantic model to include DB `id` field in the response"""

    id: str = Field(
        description="The database-assigned ID of the privacy declaration on the system. This is meant to be a read-only field, returned only in API responses"
    )


class BasicSystemResponse(System):
    """
    Extension of base pydantic model to include additional fields on the DB model that
    are relevant in API responses.

    This is still meant to be a "lightweight" model that does not reference relationships
    that may require additional querying beyond the `System` db table.
    """

    created_at: datetime


class SystemResponse(BasicSystemResponse):
    """Extension of base pydantic response model to include additional relationship fields that
    may require extra DB queries, like `privacy_declarations`, connection_config fields and cookies.

    This response model is generally useful for an API that returns a detailed view of _single_
    System record. Attempting to return bulk results with this model can lead to n+1 query issues.
    """

    privacy_declarations: Sequence[PrivacyDeclarationResponse] = Field(  # type: ignore[assignment]
        description=PrivacyDeclarationResponse.__doc__,
    )

    connection_configs: Optional[ConnectionConfigurationResponse] = Field(
        description=ConnectionConfigurationResponse.__doc__,
    )

    data_stewards: Optional[List[UserResponse]] = Field(
        description="System managers of the current system",
    )


class SystemHistoryResponse(BaseModel):
    """Response schema for a single system history entry"""

    edited_by: Optional[str] = None
    system_id: str
    before: Dict[str, Any]
    after: Dict[str, Any]
    created_at: datetime
    model_config = ConfigDict(from_attributes=True)


class AssignStewardRequest(BaseModel):
    """Request schema for assigning a data steward to one or more systems."""

    data_steward: str
    system_keys: List[FidesKey]
