"""Pydantic models for Authorisation validation."""

from typing import Optional
from pydantic import Field, model_validator

from .base import ToothFairyModel
from .enums import AuthType


AUTH_TYPE_REQUIRED_FIELDS = {
    AuthType.OAUTH: ["client_id", "client_secret", "authorization_base_url", "grant_type"],
    AuthType.BEARER: ["token_secret"],
    AuthType.APIKEY: ["token_secret"],
    AuthType.PASSWORD: ["token_secret"],
    AuthType.BASIC: ["token_secret"],
    AuthType.USERNAME_AND_PASSWORD: ["token_secret"],
}


class AuthorisationCreateModel(ToothFairyModel):
    """Validation model for creating an authorisation."""

    name: str = Field(..., min_length=1, max_length=255, description="Human-readable name")
    auth_type: AuthType = Field(..., description="Type of authorisation")
    token_secret: Optional[str] = Field(default=None, description="Token or secret value")
    description: Optional[str] = Field(default=None, description="Description")
    scope: Optional[str] = Field(default=None, description="OAuth scope")
    grant_type: Optional[str] = Field(default=None, description="OAuth grant type")
    client_id: Optional[str] = Field(default=None, description="OAuth client ID")
    client_secret: Optional[str] = Field(default=None, description="OAuth client secret")
    authorization_base_url: Optional[str] = Field(default=None, description="OAuth authorization URL")
    static_args: Optional[str] = Field(default=None, description="Static arguments as JSON string")
    token_base_url: Optional[str] = Field(default=None, description="OAuth token URL")

    @model_validator(mode="after")
    def validate_auth_type_fields(self):
        required_fields = AUTH_TYPE_REQUIRED_FIELDS.get(self.auth_type, [])
        missing = []
        for field in required_fields:
            if getattr(self, field, None) is None:
                missing.append(field)
        if missing:
            raise ValueError(
                f"auth_type='{self.auth_type.value}' requires fields: {missing}. "
                f"Please provide all required fields for this auth type."
            )
        return self

    def to_api_payload(self) -> dict:
        payload = {
            "name": self.name,
            "type": self.auth_type.value,
        }
        if self.token_secret is not None:
            payload["tokenSecret"] = self.token_secret
        if self.description is not None:
            payload["description"] = self.description
        if self.scope is not None:
            payload["scope"] = self.scope
        if self.grant_type is not None:
            payload["grantType"] = self.grant_type
        if self.client_id is not None:
            payload["clientId"] = self.client_id
        if self.client_secret is not None:
            payload["clientSecret"] = self.client_secret
        if self.authorization_base_url is not None:
            payload["authorizationBaseUrl"] = self.authorization_base_url
        if self.static_args is not None:
            payload["staticArgs"] = self.static_args
        if self.token_base_url is not None:
            payload["tokenBaseUrl"] = self.token_base_url
        return payload


class AuthorisationUpdateModel(ToothFairyModel):
    """Validation model for updating an authorisation."""

    authorisation_id: str = Field(..., min_length=1, description="Authorisation ID")
    name: Optional[str] = Field(default=None, min_length=1, max_length=255)
    auth_type: Optional[AuthType] = Field(default=None)
    token_secret: Optional[str] = Field(default=None)
    description: Optional[str] = Field(default=None)
    scope: Optional[str] = Field(default=None)
    grant_type: Optional[str] = Field(default=None)
    client_id: Optional[str] = Field(default=None)
    client_secret: Optional[str] = Field(default=None)
    authorization_base_url: Optional[str] = Field(default=None)
    static_args: Optional[str] = Field(default=None)
    token_base_url: Optional[str] = Field(default=None)

    def to_api_payload(self) -> dict:
        payload = {"id": self.authorisation_id}
        if self.name is not None:
            payload["name"] = self.name
        if self.auth_type is not None:
            payload["type"] = self.auth_type.value
        if self.token_secret is not None:
            payload["tokenSecret"] = self.token_secret
        if self.description is not None:
            payload["description"] = self.description
        if self.scope is not None:
            payload["scope"] = self.scope
        if self.grant_type is not None:
            payload["grantType"] = self.grant_type
        if self.client_id is not None:
            payload["clientId"] = self.client_id
        if self.client_secret is not None:
            payload["clientSecret"] = self.client_secret
        if self.authorization_base_url is not None:
            payload["authorizationBaseUrl"] = self.authorization_base_url
        if self.static_args is not None:
            payload["staticArgs"] = self.static_args
        if self.token_base_url is not None:
            payload["tokenBaseUrl"] = self.token_base_url
        return payload