from __future__ import annotations
import os
import yaml
from typing import Optional, Any
from pydantic import BaseModel

class SfMetadataInject(BaseModel):
    deployment: bool = True
    service_config: bool = True
    ingress: bool = True
    dockerfile: bool = True
    pyproject_toml: bool = True

class SfMetadataEndpoint(BaseModel):
    path: str
    method: str

class SfMetadataField(BaseModel):
    type: str
    description: str

class SfMetadataParameter(SfMetadataField):
    required: bool = False
    location: str = "body"
    default: Optional[Any] = None
    enum: Optional[list[Any]] = None

class SfMetadataAbility(BaseModel):
    name: str
    description: str
    endpoint: SfMetadataEndpoint
    parameters: dict[str, SfMetadataParameter]
    response: dict[str, SfMetadataField]

class SfMetadata(BaseModel):
    name: str
    version: str
    description: str
    service_config: str
    config_only: bool
    abilities: list[SfMetadataAbility] = []
    env: list[dict]
    inject: SfMetadataInject = SfMetadataInject()
    enable_auth_middleware: bool = True
    mode: str = "debug"

    @classmethod
    def from_yaml_file(cls, filepath: str) -> SfMetadata:
        with open(filepath, 'r', encoding='utf-8') as f:
            data = yaml.safe_load(f)
        return cls(**data)

def load_metadata(path: str) -> SfMetadata:
    if os.path.exists(path):
        return SfMetadata.from_yaml_file(path)
    return None

def save_metadata(meta: SfMetadata, path: str) -> None:
    with open(path, 'w', encoding='utf-8') as f:
        yaml.safe_dump(meta.model_dump(exclude_unset=True, by_alias=True), f, allow_unicode=True)

metadata = load_metadata("sf-meta.yaml")