"""Pydantic schemas for user GitHub App + mirror APIs."""
from __future__ import annotations

from datetime import datetime
from typing import Optional
from uuid import UUID

from pydantic import BaseModel, Field, model_validator


class GithubUserInstallationCreate(BaseModel):
    """Link an installation after the user completes the GitHub App install flow."""

    installation_id: Optional[int] = Field(
        None,
        gt=0,
        description="Numeric installation id from GitHub.",
    )
    installation_url: Optional[str] = Field(
        None,
        description=(
            "GitHub installation/settings URL, used to reconnect an already-installed app "
            "when GitHub does not redirect through the setup callback."
        ),
    )
    state: Optional[str] = Field(
        None,
        description="Same state from GET install-url (can be sent in body instead of query).",
    )

    @model_validator(mode="after")
    def require_installation_identity(self) -> GithubUserInstallationCreate:
        if self.installation_id is None and not (self.installation_url or "").strip():
            raise ValueError("installation_id or installation_url is required.")
        return self


class GithubUserInstallationResponse(BaseModel):
    id: UUID
    workspace_id: UUID
    github_installation_id: int
    account_login: str
    account_type: str
    repository_selection: str
    suspended_at: Optional[datetime] = None
    created_at: datetime

    model_config = {"from_attributes": True}


class GithubUserRepoItem(BaseModel):
    id: int
    full_name: str
    private: bool = False
    default_branch: Optional[str] = None


class InstallUrlResponse(BaseModel):
    install_url: str
    state: str = Field(
        ...,
        description="Opaque state; include as query param when completing (CSRF binding).",
    )
    callback_return_url: str = Field(
        ...,
        description=(
            "Full frontend URL embedded in state for post-install redirect "
            "(Setup URL target)."
        ),
    )


class ProjectMirrorUpsert(BaseModel):
    workspace_user_github_installation_id: UUID
    target_repo_full_name: str = Field(..., min_length=3, max_length=255)
    target_default_branch: str = Field(default="main", max_length=100)
    enabled: bool = True


class ProjectMirrorResponse(BaseModel):
    id: UUID
    project_id: UUID
    workspace_user_github_installation_id: UUID
    target_repo_full_name: str
    target_default_branch: str
    enabled: bool
    last_push_sha: Optional[str] = None
    last_error: Optional[str] = None

    model_config = {"from_attributes": True}
