from __future__ import annotations

from typing import Any, Dict, List, Literal, Optional

from pydantic import BaseModel, ConfigDict, Field, model_validator

from goodmem.models.credential_kind import CredentialKind
from goodmem.models.api_key_auth import ApiKeyAuth
from goodmem.models.gcp_adc_auth import GcpAdcAuth


class EndpointAuthentication(BaseModel):
    """Structured credential payload describing how GoodMem should authenticate with an upstream provider."""

    model_config = ConfigDict(populate_by_name=True, protected_namespaces=())

    kind: CredentialKind = Field(description='Selected credential strategy')
    api_key: Optional[ApiKeyAuth] = Field(default=None, description='Configuration when kind is CREDENTIAL_KIND_API_KEY', alias="apiKey")
    gcp_adc: Optional[GcpAdcAuth] = Field(default=None, description='Configuration when kind is CREDENTIAL_KIND_GCP_ADC', alias="gcpAdc")
    labels: Optional[dict[str, str]] = Field(default=None, description='Optional annotations to aid operators (e.g., "owner=vertex")')

    @model_validator(mode='after')
    def _check_mutual_exclusion(self) -> 'EndpointAuthentication':
        _fields = ['api_key', 'gcp_adc']
        _set = [f for f in _fields if getattr(self, f) is not None]
        if len(_set) > 1:
            raise ValueError('Exactly one credential payload (api_key or gcp_adc) must match the kind discriminator' + f": got {_set}")
        return self

    @model_validator(mode='after')
    def _check_kind_payload(self) -> 'EndpointAuthentication':
        _kind_to_field = {'CREDENTIAL_KIND_API_KEY': 'api_key', 'CREDENTIAL_KIND_GCP_ADC': 'gcp_adc'}
        _payload_fields = ['api_key', 'gcp_adc']
        _expected = _kind_to_field.get(self.kind.value if hasattr(self.kind, 'value') else self.kind)
        _set = [f for f in _payload_fields if getattr(self, f) is not None]
        if _expected is not None:
            if getattr(self, _expected) is None:
                raise ValueError(f"kind={self.kind} requires '{_expected}' to be set")
            _wrong = [f for f in _payload_fields if f != _expected and getattr(self, f) is not None]
            if _wrong:
                raise ValueError(f"kind={self.kind} conflicts with payload field(s): {_wrong}")
        elif (self.kind.value if hasattr(self.kind, 'value') else self.kind) == 'CREDENTIAL_KIND_UNSPECIFIED' and _set:
            raise ValueError(f"kind=CREDENTIAL_KIND_UNSPECIFIED must not have any credential payload: got {_set}")
        return self

