"""Branding / company settings: company name plus the uploaded logo and favicon.

The read endpoints are deliberately public — the browser needs the company name and
favicon on the login screen and in the tab, before an admin has signed in. Writes are
admin-only.
"""
from fastapi import APIRouter, Depends, File, HTTPException, Request, UploadFile, status
from fastapi.responses import FileResponse
from sqlalchemy.orm import Session

from app.api.deps import client_ip, require_admin
from app.db.session import get_db
from app.models.setting import Setting
from app.models.user import User
from app.schemas.setting import SettingOut, SettingUpdate
from app.services import audit, storage

router = APIRouter(prefix="/settings", tags=["settings"])

#: Served binary kinds, which also drives the URL path /settings/file/{kind}.
ASSET_KINDS = ("logo", "favicon")


def _get_or_create_settings(db: Session) -> Setting:
    """Return the singleton settings row (id = 1), creating it if a migration or a
    long-lived deployment skipped the seed."""
    row = db.get(Setting, 1)
    if row is None:
        row = Setting(id=1, company_name="ISP Management System")
        db.add(row)
        db.flush()
    return row


def _asset_url(kind: str) -> str:
    return f"/api/v1/settings/file/{kind}"


def _to_out(row: Setting) -> SettingOut:
    return SettingOut(
        company_name=row.company_name,
        logo_url=_asset_url("logo") if row.logo_path else "",
        favicon_url=_asset_url("favicon") if row.favicon_path else "",
    )


def _handle_upload(kind: str, file: UploadFile, request: Request, user: User, db: Session) -> SettingOut:
    row = _get_or_create_settings(db)
    new_path, _ = storage.save_upload(file, entity="settings", entity_id=row.id)

    old_path = getattr(row, f"{kind}_path")
    setattr(row, f"{kind}_path", new_path)
    setattr(row, f"{kind}_content_type", file.content_type or "image/png")
    db.flush()

    audit.record(
        db,
        user_id=user.id,
        action="update",
        entity_type="setting",
        entity_id=row.id,
        payload={"field": kind},
        ip_address=client_ip(request),
    )
    db.commit()
    db.refresh(row)
    # Only once the new file is safely referenced is the old one removed.
    if old_path:
        storage.delete_stored_file(old_path)
    return _to_out(row)


@router.get("", response_model=SettingOut)
def get_settings(db: Session = Depends(get_db)) -> SettingOut:
    row = _get_or_create_settings(db)
    db.commit()
    return _to_out(row)


@router.patch("", response_model=SettingOut)
def update_settings(
    payload: SettingUpdate,
    request: Request,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_admin),
) -> SettingOut:
    row = _get_or_create_settings(db)
    row.company_name = payload.company_name
    audit.record(
        db,
        user_id=current_user.id,
        action="update",
        entity_type="setting",
        entity_id=row.id,
        payload={"company_name": payload.company_name},
        ip_address=client_ip(request),
    )
    db.commit()
    db.refresh(row)
    return _to_out(row)


@router.post("/logo", response_model=SettingOut)
def upload_logo(
    request: Request,
    file: UploadFile = File(...),
    db: Session = Depends(get_db),
    current_user: User = Depends(require_admin),
) -> SettingOut:
    return _handle_upload("logo", file, request, current_user, db)


@router.post("/favicon", response_model=SettingOut)
def upload_favicon(
    request: Request,
    file: UploadFile = File(...),
    db: Session = Depends(get_db),
    current_user: User = Depends(require_admin),
) -> SettingOut:
    return _handle_upload("favicon", file, request, current_user, db)


@router.get("/file/{kind}")
def serve_asset(kind: str, db: Session = Depends(get_db)) -> FileResponse:
    if kind not in ASSET_KINDS:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Unknown asset")
    row = _get_or_create_settings(db)
    db.commit()
    path = getattr(row, f"{kind}_path")
    content_type = getattr(row, f"{kind}_content_type") or "image/png"
    if not path:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Asset not set")
    return FileResponse(
        storage.resolve_stored_path(path),
        media_type=content_type,
    )
