"""Admin router: user management, system settings, data cleanup, job control.

All endpoints require admin role.
"""

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

from app.dependencies import get_db, require_admin
from app.models.user import User
from app.schemas.admin import (
    ActivationConfigUpdate,
    AlertConfigUpdate,
    CreateUserRequest,
    DataCleanupRequest,
    JobTriggerRequest,
    JobToggle,
    RecommendationConfigUpdate,
    ScheduleConfigUpdate,
    SentimentConfigUpdate,
    SentimentTestRequest,
    PasswordReset,
    RegistrationToggle,
    SystemSettingUpdate,
    TickerUniverseUpdate,
    UserManagement,
)
from app.schemas.common import APIEnvelope
from app.services import admin_service
from app.services import alert_service
from app.services import sentiment_provider_service
from app.services import ticker_universe_service

router = APIRouter(tags=["admin"])


def _user_dict(user: User) -> dict:
    return {
        "id": user.id,
        "username": user.username,
        "role": user.role,
        "has_access": user.has_access,
        "created_at": user.created_at.isoformat() if user.created_at else None,
        "updated_at": user.updated_at.isoformat() if user.updated_at else None,
    }


# ---------------------------------------------------------------------------
# User management
# ---------------------------------------------------------------------------

@router.get("/admin/users", response_model=APIEnvelope)
async def list_users(
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    """List all user accounts."""
    users = await admin_service.list_users(db)
    return APIEnvelope(status="success", data=[_user_dict(u) for u in users])


@router.post("/admin/users", response_model=APIEnvelope, status_code=201)
async def create_user(
    body: CreateUserRequest,
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    """Create a new user account."""
    user = await admin_service.create_user(
        db, body.username, body.password, body.role, body.has_access
    )
    return APIEnvelope(status="success", data=_user_dict(user))


@router.put("/admin/users/{user_id}/access", response_model=APIEnvelope)
async def set_user_access(
    user_id: int,
    body: UserManagement,
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    """Grant or revoke API access for a user."""
    user = await admin_service.set_user_access(db, user_id, body.has_access)
    return APIEnvelope(status="success", data=_user_dict(user))


@router.put("/admin/users/{user_id}/password", response_model=APIEnvelope)
async def reset_password(
    user_id: int,
    body: PasswordReset,
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    """Reset a user's password."""
    user = await admin_service.reset_password(db, user_id, body.new_password)
    return APIEnvelope(status="success", data=_user_dict(user))


# ---------------------------------------------------------------------------
# Registration toggle
# ---------------------------------------------------------------------------

@router.put("/admin/settings/registration", response_model=APIEnvelope)
async def toggle_registration(
    body: RegistrationToggle,
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    """Enable or disable user registration."""
    setting = await admin_service.toggle_registration(db, body.enabled)
    return APIEnvelope(
        status="success",
        data={"key": setting.key, "value": setting.value},
    )


# ---------------------------------------------------------------------------
# System settings
# ---------------------------------------------------------------------------

@router.get("/admin/settings", response_model=APIEnvelope)
async def list_settings(
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    """List all system settings."""
    settings_list = await admin_service.list_settings(db)
    return APIEnvelope(
        status="success",
        data=[
            {"key": s.key, "value": s.value, "updated_at": s.updated_at.isoformat() if s.updated_at else None}
            for s in settings_list
        ],
    )


@router.get("/admin/settings/recommendations", response_model=APIEnvelope)
async def get_recommendation_settings(
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    config = await admin_service.get_recommendation_config(db)
    return APIEnvelope(status="success", data=config)


@router.put("/admin/settings/recommendations", response_model=APIEnvelope)
async def update_recommendation_settings(
    body: RecommendationConfigUpdate,
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    updated = await admin_service.update_recommendation_config(
        db,
        body.model_dump(exclude_unset=True),
    )
    return APIEnvelope(status="success", data=updated)


@router.get("/admin/settings/activation", response_model=APIEnvelope)
async def get_activation_settings(
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    config = await admin_service.get_activation_config(db)
    return APIEnvelope(status="success", data=config)


@router.put("/admin/settings/activation", response_model=APIEnvelope)
async def update_activation_settings(
    body: ActivationConfigUpdate,
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    updated = await admin_service.update_activation_config(
        db,
        body.model_dump(exclude_unset=True, exclude_none=True),
    )
    return APIEnvelope(status="success", data=updated)


@router.get("/admin/settings/schedule", response_model=APIEnvelope)
async def get_schedule_settings(
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    config = await admin_service.get_schedule_config(db)
    return APIEnvelope(status="success", data=config)


@router.put("/admin/settings/schedule", response_model=APIEnvelope)
async def update_schedule_settings(
    body: ScheduleConfigUpdate,
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    updated = await admin_service.update_schedule_config(
        db,
        body.model_dump(exclude_unset=True, exclude_none=True),
    )
    return APIEnvelope(status="success", data=updated)


@router.get("/admin/settings/sentiment", response_model=APIEnvelope)
async def get_sentiment_settings(
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    config = await sentiment_provider_service.get_sentiment_config(db)
    return APIEnvelope(status="success", data=config)


@router.put("/admin/settings/sentiment", response_model=APIEnvelope)
async def update_sentiment_settings(
    body: SentimentConfigUpdate,
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    config = await sentiment_provider_service.update_sentiment_config(
        db,
        provider=body.provider,
        model=body.model,
        api_key=body.api_key,
        base_url=body.base_url,
    )
    return APIEnvelope(status="success", data=config)


@router.post("/admin/settings/sentiment/test", response_model=APIEnvelope)
async def test_sentiment_settings(
    body: SentimentTestRequest,
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    """Live credentials check: fetch sentiment for one ticker with current config."""
    result = await sentiment_provider_service.test_sentiment_provider(db, body.ticker)
    return APIEnvelope(status="success", data=result)


@router.get("/admin/settings/alerts", response_model=APIEnvelope)
async def get_alert_settings(
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    config = await alert_service.get_alert_config(db)
    return APIEnvelope(status="success", data=config)


@router.put("/admin/settings/alerts", response_model=APIEnvelope)
async def update_alert_settings(
    body: AlertConfigUpdate,
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    config = await alert_service.update_alert_config(
        db, **body.model_dump(exclude_unset=True)
    )
    return APIEnvelope(status="success", data=config)


@router.post("/admin/settings/alerts/test", response_model=APIEnvelope)
async def test_alert_settings(
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    """Send a test Telegram message with the current config."""
    result = await alert_service.send_test_alert(db)
    return APIEnvelope(status="success", data=result)


@router.get("/admin/settings/ticker-universe", response_model=APIEnvelope)
async def get_ticker_universe_setting(
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    data = await admin_service.get_ticker_universe_default(db)
    return APIEnvelope(status="success", data=data)


@router.put("/admin/settings/ticker-universe", response_model=APIEnvelope)
async def update_ticker_universe_setting(
    body: TickerUniverseUpdate,
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    data = await admin_service.update_ticker_universe_default(db, body.universe)
    return APIEnvelope(status="success", data=data)


@router.put("/admin/settings/{key}", response_model=APIEnvelope)
async def update_setting(
    key: str,
    body: SystemSettingUpdate,
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    """Create or update a system setting."""
    setting = await admin_service.update_setting(db, key, body.value)
    return APIEnvelope(
        status="success",
        data={"key": setting.key, "value": setting.value, "updated_at": setting.updated_at.isoformat() if setting.updated_at else None},
    )


@router.post("/admin/tickers/bootstrap", response_model=APIEnvelope)
async def bootstrap_tickers(
    universe: str = Query("sp500", pattern="^(sp500|nasdaq100|nasdaq_all)$"),
    prune_missing: bool = Query(False),
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    result = await ticker_universe_service.bootstrap_universe(
        db,
        universe,
        prune_missing=prune_missing,
    )
    return APIEnvelope(status="success", data=result)


@router.post("/admin/tickers/backfill-names", response_model=APIEnvelope)
async def backfill_ticker_names(
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    """Fill in company names for tracked tickers (one Alpaca call)."""
    result = await ticker_universe_service.backfill_ticker_names(db)
    return APIEnvelope(status="success", data=result)


# ---------------------------------------------------------------------------
# Data cleanup
# ---------------------------------------------------------------------------

@router.post("/admin/data/cleanup", response_model=APIEnvelope)
async def cleanup_data(
    body: DataCleanupRequest,
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    """Delete OHLCV, sentiment, and fundamental data older than N days."""
    counts = await admin_service.cleanup_data(db, body.older_than_days)
    return APIEnvelope(status="success", data=counts)


@router.post("/admin/track-record/reset", response_model=APIEnvelope)
async def reset_track_record(
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    """Wipe the track record: delete all trade setups so stats start fresh."""
    counts = await admin_service.reset_trade_setups(db)
    return APIEnvelope(status="success", data=counts)


# ---------------------------------------------------------------------------
# Job control
# ---------------------------------------------------------------------------

@router.get("/admin/jobs", response_model=APIEnvelope)
async def list_jobs(
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    """List all scheduled jobs with their current status."""
    jobs = await admin_service.list_jobs(db)
    return APIEnvelope(status="success", data=jobs)


@router.get("/admin/pipeline/readiness", response_model=APIEnvelope)
async def get_pipeline_readiness(
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    data = await admin_service.get_pipeline_readiness(db)
    return APIEnvelope(status="success", data=data)


@router.post("/admin/jobs/{job_name}/trigger", response_model=APIEnvelope)
async def trigger_job(
    job_name: str,
    body: JobTriggerRequest | None = None,
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    """Trigger a manual job run, optionally with one-run parameters."""
    result = await admin_service.trigger_job(
        db,
        job_name,
        target_model=body.target_model if body is not None else None,
    )
    return APIEnvelope(status="success", data=result)


@router.put("/admin/jobs/{job_name}/toggle", response_model=APIEnvelope)
async def toggle_job(
    job_name: str,
    body: JobToggle,
    _admin: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    """Enable or disable a scheduled job (placeholder)."""
    setting = await admin_service.toggle_job(db, job_name, body.enabled)
    return APIEnvelope(
        status="success",
        data={"key": setting.key, "value": setting.value},
    )
