# #region GitSchemas [C:1] [TYPE Module] [SEMANTICS fastapi, git, api, git-server-config-base]
#
# @BRIEF Defines Pydantic models for the Git integration API layer.
# @LAYER     API
# @RELATION DEPENDS_ON -> [GitModels]
#
# @INVARIANT  All schemas must be compatible with the FastAPI router.

from datetime import datetime
from typing import Any

from pydantic import BaseModel, ConfigDict, Field

from src.models.git import GitProvider, GitStatus, SyncStatus


# #region GitServerConfigBase [C:1] [TYPE Class]
# @BRIEF Base schema for Git server configuration attributes.
class GitServerConfigBase(BaseModel):
    name: str = Field(..., description="Display name for the Git server")
    provider: GitProvider = Field(..., description="Git provider (GITHUB, GITLAB, GITEA)")
    url: str = Field(..., description="Server base URL")
    pat: str = Field(..., description="Personal Access Token")
    pat: str = Field(..., description="Personal Access Token")
    default_repository: str | None = Field(None, description="Default repository path (org/repo)")
    default_branch: str | None = Field("main", description="Default branch logic/name")
# #endregion GitServerConfigBase

# #region GitServerConfigUpdate [TYPE Class]
# @BRIEF Schema for updating an existing Git server configuration.
class GitServerConfigUpdate(BaseModel):
    name: str | None = Field(None, description="Display name for the Git server")
    provider: GitProvider | None = Field(None, description="Git provider (GITHUB, GITLAB, GITEA)")
    url: str | None = Field(None, description="Server base URL")
    pat: str | None = Field(None, description="Personal Access Token")
    default_repository: str | None = Field(None, description="Default repository path (org/repo)")
    default_branch: str | None = Field(None, description="Default branch logic/name")
# #endregion GitServerConfigUpdate

# #region GitServerConfigCreate [TYPE Class]
# @BRIEF Schema for creating a new Git server configuration.
class GitServerConfigCreate(GitServerConfigBase):
    """Schema for creating a new Git server configuration."""
    config_id: str | None = Field(None, description="Optional config ID, useful for testing an existing config without sending its full PAT")
# #endregion GitServerConfigCreate

# #region GitServerConfigSchema [TYPE Class]
# @BRIEF Schema for representing a Git server configuration with metadata.
class GitServerConfigSchema(GitServerConfigBase):
    """Schema for representing a Git server configuration with metadata."""
    id: str
    status: GitStatus
    last_validated: datetime

    model_config = ConfigDict(from_attributes=True)
# #endregion GitServerConfigSchema

# #region GitRepositorySchema [TYPE Class]
# @BRIEF Schema for tracking a local Git repository linked to a dashboard.
class GitRepositorySchema(BaseModel):
    """Schema for tracking a local Git repository linked to a dashboard."""
    id: str
    dashboard_id: int
    config_id: str
    remote_url: str
    local_path: str
    current_branch: str
    sync_status: SyncStatus

    model_config = ConfigDict(from_attributes=True)
# #endregion GitRepositorySchema

# #region BranchSchema [TYPE Class]
# @BRIEF Schema for representing a Git branch metadata.
class BranchSchema(BaseModel):
    """Schema for representing a Git branch."""
    name: str
    commit_hash: str
    is_remote: bool
    last_updated: datetime
# #endregion BranchSchema

# #region CommitSchema [TYPE Class]
# @BRIEF Schema for representing Git commit details.
class CommitSchema(BaseModel):
    """Schema for representing a Git commit."""
    hash: str
    author: str
    email: str
    timestamp: datetime
    message: str
    files_changed: list[str]
# #endregion CommitSchema

# #region BranchCreate [TYPE Class]
# @BRIEF Schema for branch creation requests.
class BranchCreate(BaseModel):
    """Schema for branch creation requests."""
    name: str
    from_branch: str
# #endregion BranchCreate

# #region BranchCheckout [TYPE Class]
# @BRIEF Schema for branch checkout requests.
class BranchCheckout(BaseModel):
    """Schema for branch checkout requests."""
    name: str
# #endregion BranchCheckout

# #region CommitCreate [TYPE Class]
# @BRIEF Schema for staging and committing changes.
class CommitCreate(BaseModel):
    """Schema for staging and committing changes."""
    message: str
    files: list[str]
# #endregion CommitCreate

# #region ConflictResolution [TYPE Class]
# @BRIEF Schema for resolving merge conflicts.
class ConflictResolution(BaseModel):
    """Schema for resolving merge conflicts."""
    file_path: str
    resolution: str = Field(pattern="^(mine|theirs|manual)$")
    content: str | None = None
# #endregion ConflictResolution


# #region MergeStatusSchema [TYPE Class]
# @BRIEF Schema representing unfinished merge status for repository.
class MergeStatusSchema(BaseModel):
    has_unfinished_merge: bool
    repository_path: str
    git_dir: str
    current_branch: str
    merge_head: str | None = None
    merge_message_preview: str | None = None
    conflicts_count: int = 0
# #endregion MergeStatusSchema


# #region MergeConflictFileSchema [TYPE Class]
# @BRIEF Schema describing one conflicted file with optional side snapshots.
class MergeConflictFileSchema(BaseModel):
    file_path: str
    mine: str | None = None
    theirs: str | None = None
# #endregion MergeConflictFileSchema


# #region MergeResolveRequest [TYPE Class]
# @BRIEF Request schema for resolving one or multiple merge conflicts.
class MergeResolveRequest(BaseModel):
    resolutions: list[ConflictResolution] = Field(default_factory=list)
# #endregion MergeResolveRequest


# #region MergeContinueRequest [TYPE Class]
# @BRIEF Request schema for finishing merge with optional explicit commit message.
class MergeContinueRequest(BaseModel):
    message: str | None = None
# #endregion MergeContinueRequest

# #region DeploymentEnvironmentSchema [TYPE Class]
# @BRIEF Schema for representing a target deployment environment.
class DeploymentEnvironmentSchema(BaseModel):
    """Schema for representing a target deployment environment."""
    id: str
    name: str
    superset_url: str
    is_active: bool

    model_config = ConfigDict(from_attributes=True)
# #endregion DeploymentEnvironmentSchema

# #region DeployRequest [TYPE Class]
# @BRIEF Schema for dashboard deployment requests.
class DeployRequest(BaseModel):
    """Schema for deployment requests."""
    environment_id: str
# #endregion DeployRequest

# #region RepoInitRequest [TYPE Class]
# @BRIEF Schema for repository initialization requests.
class RepoInitRequest(BaseModel):
    """Schema for repository initialization requests."""
    config_id: str
    remote_url: str
# #endregion RepoInitRequest


# #region RepositoryBindingSchema [TYPE Class]
# @BRIEF Schema describing repository-to-config binding and provider metadata.
class RepositoryBindingSchema(BaseModel):
    dashboard_id: int
    config_id: str
    provider: GitProvider
    remote_url: str
    local_path: str
# #endregion RepositoryBindingSchema

# #region RepoStatusBatchRequest [TYPE Class]
# @BRIEF Schema for requesting repository statuses for multiple dashboards in a single call.
class RepoStatusBatchRequest(BaseModel):
    dashboard_ids: list[int] = Field(default_factory=list, description="Dashboard IDs to resolve repository statuses for")
# #endregion RepoStatusBatchRequest


# #region RepoStatusBatchResponse [TYPE Class]
# @BRIEF Schema for returning repository statuses keyed by dashboard ID.
class RepoStatusBatchResponse(BaseModel):
    statuses: dict[str, dict[str, Any]]
# #endregion RepoStatusBatchResponse


# #region GiteaRepoSchema [TYPE Class]
# @BRIEF Schema describing a Gitea repository.
class GiteaRepoSchema(BaseModel):
    name: str
    full_name: str
    private: bool = False
    clone_url: str | None = None
    html_url: str | None = None
    ssh_url: str | None = None
    default_branch: str | None = None
# #endregion GiteaRepoSchema


# #region GiteaRepoCreateRequest [TYPE Class]
# @BRIEF Request schema for creating a Gitea repository.
class GiteaRepoCreateRequest(BaseModel):
    name: str = Field(..., min_length=1, max_length=255)
    private: bool = True
    description: str | None = None
    auto_init: bool = True
    default_branch: str | None = "main"
# #endregion GiteaRepoCreateRequest


# #region RemoteRepoSchema [TYPE Class]
# @BRIEF Provider-agnostic remote repository payload.
class RemoteRepoSchema(BaseModel):
    provider: GitProvider
    name: str
    full_name: str
    private: bool = False
    clone_url: str | None = None
    html_url: str | None = None
    ssh_url: str | None = None
    default_branch: str | None = None
# #endregion RemoteRepoSchema


# #region RemoteRepoCreateRequest [TYPE Class]
# @BRIEF Provider-agnostic repository creation request.
class RemoteRepoCreateRequest(BaseModel):
    name: str = Field(..., min_length=1, max_length=255)
    private: bool = True
    description: str | None = None
    auto_init: bool = True
    default_branch: str | None = "main"
# #endregion RemoteRepoCreateRequest


# #region PromoteRequest [TYPE Class]
# @BRIEF Request schema for branch promotion workflow.
class PromoteRequest(BaseModel):
    from_branch: str = Field(..., min_length=1, max_length=255)
    to_branch: str = Field(..., min_length=1, max_length=255)
    mode: str = Field(default="mr", pattern="^(mr|direct)$")
    title: str | None = None
    description: str | None = None
    reason: str | None = None
    draft: bool = False
    remove_source_branch: bool = False
# #endregion PromoteRequest


# #region PromoteResponse [TYPE Class]
# @BRIEF Response schema for promotion operation result.
class PromoteResponse(BaseModel):
    mode: str
    from_branch: str
    to_branch: str
    status: str
    url: str | None = None
    reference_id: str | None = None
    policy_violation: bool = False
# #endregion PromoteResponse

# #endregion GitSchemas
