"""Schemas for Forgejo connection CRUD API payloads."""

from __future__ import annotations

from datetime import datetime
from uuid import UUID

from pydantic import field_validator
from sqlmodel import Field, SQLModel

RUNTIME_ANNOTATION_TYPES = (datetime, UUID)


class ForgejoConnectionBase(SQLModel):
    """Shared connection fields used across create/read payloads."""

    name: str
    base_url: str
    token: str | None = None
    active: bool = True

    @field_validator("base_url", mode="before")
    @classmethod
    def normalize_base_url(cls, value: object) -> str | None | object:
        """Normalize base_url - ensure it's a valid http/https URL without /api/v1 path."""
        if value is None:
            return None
        if isinstance(value, str):
            value = value.strip()
            if not value:
                return None
            # Remove trailing slashes
            value = value.rstrip("/")
            # Validate protocol
            if not value.startswith(("http://", "https://")):
                raise ValueError("base_url must be http:// or https://")
            # Remove /api/v1 if present
            if "/api/v1" in value:
                # Find the base host
                import re
                match = re.match(r"(https?://[^/]+)", value)
                if match:
                    value = match.group(1).rstrip("/")
            return value
        return value

    @field_validator("token", mode="before")
    @classmethod
    def normalize_token(cls, value: object) -> str | None | object:
        """Normalize empty/whitespace tokens to `None`."""
        if value is None:
            return None
        if isinstance(value, str):
            value = value.strip()
            return value or None
        return value


class ForgejoConnectionCreate(ForgejoConnectionBase):
    """Payload for creating a Forgejo connection configuration."""


class ForgejoConnectionUpdate(SQLModel):
    """Payload for partial Forgejo connection updates."""

    name: str | None = None
    base_url: str | None = None
    token: str | None = None
    active: bool | None = None

    @field_validator("base_url", mode="before")
    @classmethod
    def normalize_base_url(cls, value: object) -> str | None | object:
        """Normalize base_url - ensure it's a valid http/https URL without /api/v1 path."""
        if value is None:
            return None
        if isinstance(value, str):
            value = value.strip()
            if not value:
                return None
            value = value.rstrip("/")
            if not value.startswith(("http://", "https://")):
                raise ValueError("base_url must be http:// or https://")
            if "/api/v1" in value:
                import re
                match = re.match(r"(https?://[^/]+)", value)
                if match:
                    value = match.group(1).rstrip("/")
            return value
        return value

    @field_validator("token", mode="before")
    @classmethod
    def normalize_token(cls, value: object) -> str | None | object:
        """Normalize empty/whitespace tokens to `None`."""
        if value is None:
            return None
        if isinstance(value, str):
            value = value.strip()
            return value or None
        return value


class ForgejoConnectionTestRequest(SQLModel):
    """Payload for testing a connection before saving it."""

    base_url: str
    token: str


class ForgejoConnectionTestRepo(SQLModel):
    """Minimal repo info returned in a connection test."""

    full_name: str
    name: str
    owner: str
    default_branch: str
    private: bool
    description: str | None = None


class ForgejoConnectionTestResponse(SQLModel):
    """Result of a pre-save connection test."""

    valid: bool
    user_login: str | None = None
    user_full_name: str | None = None
    repo_count: int = 0
    repos: list[ForgejoConnectionTestRepo] = []
    error: str | None = None
    response_time_ms: float = 0.0


class ForgejoConnectionRead(ForgejoConnectionBase):
    """Connection payload returned from read endpoints."""

    id: UUID
    organization_id: UUID
    has_token: bool
    token_last_eight: str | None
    created_at: datetime
    updated_at: datetime
