import os
import platform
from datetime import datetime, timezone

from fastapi import APIRouter, Depends
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.config import get_settings
from app.core.db import get_db
from app.core.deps import get_current_user
from app.models.models import ServiceInfoSettings, User
from app.schemas.service_info import ServiceInfoCheckResult, ServiceInfoOut
from app.services.service_info import (
    UPSTREAM_REPO_WEB,
    fetch_latest_from_upstream,
    is_update_available,
    utcnow,
)

router = APIRouter()
settings = get_settings()
service_started_at = datetime.now(timezone.utc)


async def _get_or_create_service_settings(db: AsyncSession) -> ServiceInfoSettings:
    row = await db.scalar(select(ServiceInfoSettings).limit(1))
    if row:
        return row
    row = ServiceInfoSettings(current_version=settings.app_version)
    db.add(row)
    await db.commit()
    await db.refresh(row)
    return row


def _to_out(row: ServiceInfoSettings) -> ServiceInfoOut:
    uptime_seconds = int((utcnow() - service_started_at).total_seconds())
    return ServiceInfoOut(
        app_name=settings.app_name,
        environment=settings.environment,
        api_prefix=settings.api_v1_prefix,
        app_version=settings.app_version,
        hostname=platform.node() or os.getenv("HOSTNAME", "unknown"),
        python_version=platform.python_version(),
        platform=platform.platform(),
        service_started_at=service_started_at,
        uptime_seconds=max(uptime_seconds, 0),
        update_source=UPSTREAM_REPO_WEB,
        latest_version=row.latest_version,
        latest_ref=(row.release_check_url or None),
        update_available=row.update_available,
        last_checked_at=row.last_checked_at,
        last_check_error=row.last_check_error,
    )


@router.get("/info", response_model=ServiceInfoOut)
async def get_service_info(
    user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
) -> ServiceInfoOut:
    _ = user
    row = await _get_or_create_service_settings(db)
    return _to_out(row)


@router.post("/info/check", response_model=ServiceInfoCheckResult)
async def check_service_version(
    user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
) -> ServiceInfoCheckResult:
    _ = user
    row = await _get_or_create_service_settings(db)
    check_time = utcnow()
    latest, latest_ref, error = await fetch_latest_from_upstream()

    row.last_checked_at = check_time
    row.last_check_error = error
    if latest:
        row.latest_version = latest
        row.release_check_url = latest_ref
        row.update_available = is_update_available(settings.app_version, latest)
    else:
        row.update_available = False
    await db.commit()
    await db.refresh(row)
    return ServiceInfoCheckResult(
        latest_version=row.latest_version,
        latest_ref=(row.release_check_url or None),
        update_available=row.update_available,
        last_checked_at=row.last_checked_at or check_time,
        last_check_error=row.last_check_error,
    )
