# /opt/docker/dev/service_finder/backend/app/api/v1/endpoints/admin.py
from fastapi import APIRouter, Depends, HTTPException, status, Body, BackgroundTasks
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func, text, delete
from typing import List, Any, Dict, Optional
from datetime import datetime, timedelta

from app.api import deps
from app.models.identity import User, UserRole # JAVÍTVA: Központi import
from app.models.system import SystemParameter, ParameterScope
from app.services.system_service import system_service
# JAVÍTVA: Security audit modellek
from app.models import SecurityAuditLog, OperationalLog
# JAVÍTVA: Ezek a modellek a security.py-ból jönnek (ha ott vannak)
from app.models import PendingAction, ActionStatus

from app.services.security_service import security_service
from app.services.translation_service import TranslationService
from app.services.odometer_service import OdometerService
from pydantic import BaseModel, Field
from typing import Optional as Opt

class ConfigUpdate(BaseModel):
    key: str
    value: Any
    scope_level: ParameterScope = ParameterScope.GLOBAL
    scope_id: Optional[str] = None
    category: str = "general"

router = APIRouter()

async def check_admin_access(current_user: User = Depends(deps.get_current_active_user)):
    """ Csak Admin vagy Superadmin. """
    if current_user.role not in [UserRole.admin, UserRole.superadmin]:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN, 
            detail="Sentinel jogosultság szükséges!"
        )
    return current_user

@router.get("/health-monitor", tags=["Sentinel Monitoring"])
async def get_system_health(
    db: AsyncSession = Depends(deps.get_db),
    admin: User = Depends(check_admin_access)
):
    stats = {}
    
    # Adatbázis statisztikák (Nyers SQL marad, mert hatékony)
    user_stats = await db.execute(text("SELECT subscription_plan, count(*) FROM identity.users GROUP BY subscription_plan"))
    stats["user_distribution"] = {row[0]: row[1] for row in user_stats}
    
    asset_count = await db.execute(text("SELECT count(*) FROM vehicle.assets"))
    stats["total_assets"] = asset_count.scalar()
    
    org_count = await db.execute(text("SELECT count(*) FROM fleet.organizations"))
    stats["total_organizations"] = org_count.scalar()

    # JAVÍTVA: Biztonsági státusz az új SecurityAuditLog alapján
    day_ago = datetime.now() - timedelta(days=1)
    crit_logs = await db.execute(
        select(func.count(SecurityAuditLog.id))
        .where(
            SecurityAuditLog.is_critical == True,
            SecurityAuditLog.created_at >= day_ago
        )
    )
    stats["critical_alerts_24h"] = crit_logs.scalar() or 0

    return stats

@router.get("/pending-actions", response_model=List[Any], tags=["Sentinel Security"])
async def list_pending_actions(
    db: AsyncSession = Depends(deps.get_db),
    admin: User = Depends(check_admin_access)
):
    stmt = select(PendingAction).where(PendingAction.status == ActionStatus.pending)
    result = await db.execute(stmt)
    return result.scalars().all()

@router.post("/approve/{action_id}", tags=["Sentinel Security"])
async def approve_action(
    action_id: int,
    db: AsyncSession = Depends(deps.get_db),
    admin: User = Depends(check_admin_access)
):
    try:
        await security_service.approve_action(db, admin.id, action_id)
        return {"status": "success", "message": "Művelet végrehajtva."}
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))

@router.get("/parameters", tags=["Dynamic Configuration"])
async def list_all_parameters(
    db: AsyncSession = Depends(deps.get_db), 
    admin: User = Depends(check_admin_access)
):
    result = await db.execute(select(SystemParameter))
    return result.scalars().all()

@router.post("/parameters", tags=["Dynamic Configuration"])
async def set_parameter(
    config: ConfigUpdate,
    db: AsyncSession = Depends(deps.get_db),
    admin: User = Depends(check_admin_access)
):
    query = text("""
        INSERT INTO system.system_parameters (key, value, scope_level, scope_id, category, last_modified_by)
        VALUES (:key, :val, :sl, :sid, :cat, :user)
        ON CONFLICT (key, scope_level, scope_id) 
        DO UPDATE SET 
            value = EXCLUDED.value, 
            category = EXCLUDED.category,
            last_modified_by = EXCLUDED.last_modified_by, 
            updated_at = now()
    """)
    
    await db.execute(query, {
        "key": config.key, 
        "val": config.value, 
        "sl": config.scope_level, 
        "sid": config.scope_id, 
        "cat": config.category, 
        "user": admin.email
    })
    await db.commit()
    return {"status": "success", "message": f"'{config.key}' frissítve."}

@router.get("/parameters/scoped", tags=["Dynamic Configuration"])
async def get_scoped_parameter(
    key: str,
    user_id: Optional[str] = None,
    region_id: Optional[str] = None,
    country_code: Optional[str] = None,
    db: AsyncSession = Depends(deps.get_db),
    admin: User = Depends(check_admin_access)
):
    """
    Hierarchikus paraméterlekérdezés a következő prioritással:
    User > Region > Country > Global.
    """
    value = await system_service.get_scoped_parameter(
        db, key, user_id, region_id, country_code, default=None
    )
    if value is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Paraméter '{key}' nem található a megadott scope-okban."
        )
    return {"key": key, "value": value}

@router.post("/translations/sync", tags=["System Utilities"])
async def sync_translations_to_json(
    db: AsyncSession = Depends(deps.get_db),
    admin: User = Depends(check_admin_access)
):
    await TranslationService.export_to_json(db)
    return {"message": "JSON fájlok frissítve."}


# ==================== SMART ODOMETER ADMIN API ====================

class OdometerStatsResponse(BaseModel):
    vehicle_id: int
    last_recorded_odometer: int
    last_recorded_date: datetime
    daily_avg_distance: float
    estimated_current_odometer: float
    confidence_score: float
    manual_override_avg: Opt[float]
    is_confidence_high: bool = Field(..., description="True ha confidence_score >= threshold")

class ManualOverrideRequest(BaseModel):
    daily_avg: Opt[float] = Field(None, description="Napi átlagos kilométer (km/nap). Ha null, törli a manuális beállítást.")

@router.get("/odometer/{vehicle_id}", tags=["Smart Odometer"])
async def get_odometer_stats(
    vehicle_id: int,
    db: AsyncSession = Depends(deps.get_db),
    admin: User = Depends(check_admin_access)
):
    """
    Jármű kilométeróra statisztikáinak lekérése.
    
    A rendszer automatikusan frissíti a statisztikákat, ha szükséges.
    """
    # Frissítjük a statisztikákat
    odometer_state = await OdometerService.update_vehicle_stats(db, vehicle_id)
    if not odometer_state:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Jármű nem található ID: {vehicle_id}"
        )
    
    # Confidence threshold lekérése
    confidence_threshold = await OdometerService.get_system_param(
        db, 'ODOMETER_CONFIDENCE_THRESHOLD', 0.5
    )
    
    return OdometerStatsResponse(
        vehicle_id=odometer_state.vehicle_id,
        last_recorded_odometer=odometer_state.last_recorded_odometer,
        last_recorded_date=odometer_state.last_recorded_date,
        daily_avg_distance=float(odometer_state.daily_avg_distance),
        estimated_current_odometer=float(odometer_state.estimated_current_odometer),
        confidence_score=odometer_state.confidence_score,
        manual_override_avg=float(odometer_state.manual_override_avg) if odometer_state.manual_override_avg else None,
        is_confidence_high=odometer_state.confidence_score >= confidence_threshold
    )

@router.patch("/odometer/{vehicle_id}", tags=["Smart Odometer"])
async def set_odometer_manual_override(
    vehicle_id: int,
    request: ManualOverrideRequest,
    db: AsyncSession = Depends(deps.get_db),
    admin: User = Depends(check_admin_access)
):
    """
    Adminisztrátori manuális átlag beállítása a kilométeróra becsléshez.
    
    Ha a user csal vagy hibás az adat, az admin ezzel felülírhatja az automatikus számítást.
    """
    odometer_state = await OdometerService.set_manual_override(
        db, vehicle_id, request.daily_avg
    )
    
    if not odometer_state:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Jármű nem található ID: {vehicle_id}"
        )
    
    action = "beállítva" if request.daily_avg is not None else "törölve"
    return {
        "status": "success",
        "message": f"Manuális átlag {action}: {request.daily_avg} km/nap",
        "vehicle_id": vehicle_id,
        "manual_override_avg": odometer_state.manual_override_avg
    }

@router.get("/ping", tags=["Admin Test"])
async def admin_ping(
    current_user: User = Depends(deps.get_current_admin)
):
    """
    Egyszerű ping végpont admin jogosultság ellenőrzéséhez.
    """
    return {
        "message": "Admin felület aktív",
        "role": current_user.role.value if hasattr(current_user.role, "value") else current_user.role
    }


@router.post("/users/{user_id}/ban", tags=["Admin Security"])
async def ban_user(
    user_id: int,
    reason: str = Body(..., embed=True),
    current_admin: User = Depends(deps.get_current_admin),
    db: AsyncSession = Depends(deps.get_db)
):
    """
    Felhasználó tiltása (Ban Hammer).
    
    - Megkeresi a usert (identity.users táblában).
    - Ha nincs -> 404
    - Ha a user.role == superadmin -> 403 (Saját magát/másik admint ne tiltson le).
    - Állítja be a tiltást (is_active = False).
    - Audit logba rögzíti a reason-t.
    """
    from sqlalchemy import select
    
    # 1. Keresd meg a usert
    stmt = select(User).where(User.id == user_id)
    result = await db.execute(stmt)
    user = result.scalar_one_or_none()
    
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"User not found with ID: {user_id}"
        )
    
    # 2. Ellenőrizd, hogy nem superadmin-e
    if user.role == UserRole.superadmin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Cannot ban a superadmin user"
        )
    
    # 3. Tiltás beállítása
    user.is_active = False
    # Opcionálisan: banned_until mező kitöltése, ha létezik a modellben
    # user.banned_until = datetime.now() + timedelta(days=30)
    
    # 4. Audit log létrehozása
    audit_log = SecurityAuditLog(
        user_id=current_admin.id,
        action="ban_user",
        target_user_id=user_id,
        details=f"User banned. Reason: {reason}",
        is_critical=True,
        ip_address="admin_api"
    )
    db.add(audit_log)
    
    await db.commit()
    
    return {
        "status": "success",
        "message": f"User {user_id} banned successfully.",
        "reason": reason
    }


@router.post("/marketplace/services/{staging_id}/approve", tags=["Marketplace Moderation"])
async def approve_staged_service(
    staging_id: int,
    current_admin: User = Depends(deps.get_current_admin),
    db: AsyncSession = Depends(deps.get_db)
):
    """
    Szerviz jóváhagyása a Piactéren (Kék Pipa).
    
    - Megkeresi a marketplace.service_staging rekordot.
    - Ha nincs -> 404
    - Állítja a validation_level-t 100-ra, a status-t 'approved'-ra.
    """
    from sqlalchemy import select
    from app.models.staged_data import ServiceStaging
    
    stmt = select(ServiceStaging).where(ServiceStaging.id == staging_id)
    result = await db.execute(stmt)
    staging = result.scalar_one_or_none()
    
    if not staging:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Service staging record not found with ID: {staging_id}"
        )
    
    # Jóváhagyás
    staging.validation_level = 100
    staging.status = "approved"
    
    # Audit log
    audit_log = SecurityAuditLog(
        user_id=current_admin.id,
        action="approve_service",
        target_staging_id=staging_id,
        details=f"Service staging approved: {staging.service_name}",
        is_critical=False,
        ip_address="admin_api"
    )
    db.add(audit_log)
    
    await db.commit()
    
    return {
        "status": "success",
        "message": f"Service staging {staging_id} approved.",
        "service_name": staging.service_name
    }


# ==================== EPIC 10: ADMIN FRONTEND API ENDPOINTS ====================

from app.workers.service.validation_pipeline import ValidationPipeline
from app.models.marketplace.service import ServiceProfile
from app.models.gamification.gamification import UserStats


class LocationUpdate(BaseModel):
    latitude: float = Field(..., ge=-90, le=90)
    longitude: float = Field(..., ge=-180, le=180)


class PenaltyRequest(BaseModel):
    penalty_level: int = Field(..., ge=-10, le=-1, description="Negatív szint (-1 a legkisebb, -10 a legnagyobb büntetés)")
    reason: str = Field(..., min_length=5, max_length=500)


@router.post("/services/{service_id}/trigger-ai", tags=["AI Pipeline"])
async def trigger_ai_pipeline(
    service_id: int,
    background_tasks: BackgroundTasks,
    current_admin: User = Depends(deps.get_current_admin),
    db: AsyncSession = Depends(deps.get_db)
):
    """
    AI Pipeline manuális indítása egy adott szerviz profilra.
    
    A végpont azonnal visszatér, és a validációt háttérfeladatként futtatja.
    """
    # Ellenőrizzük, hogy létezik-e a szerviz profil
    stmt = select(ServiceProfile).where(ServiceProfile.id == service_id)
    result = await db.execute(stmt)
    profile = result.scalar_one_or_none()
    
    if not profile:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Service profile not found with ID: {service_id}"
        )
    
    # Háttérfeladat hozzáadása
    background_tasks.add_task(run_validation_pipeline, service_id)
    
    # Audit log
    audit_log = SecurityAuditLog(
        user_id=current_admin.id,
        action="trigger_ai_pipeline",
        target_service_id=service_id,
        details=f"AI pipeline manually triggered for service {service_id}",
        is_critical=False,
        ip_address="admin_api"
    )
    db.add(audit_log)
    await db.commit()
    
    return {
        "status": "success",
        "message": f"AI pipeline started for service {service_id}",
        "service_name": profile.service_name,
        "note": "Validation runs in background, check logs for results."
    }


async def run_validation_pipeline(profile_id: int):
    """Háttérfeladat a ValidationPipeline futtatásához."""
    try:
        pipeline = ValidationPipeline()
        success = await pipeline.run(profile_id)
        logger = logging.getLogger("Service-AI-Pipeline")
        if success:
            logger.info(f"Pipeline successful for profile {profile_id}")
        else:
            logger.warning(f"Pipeline failed for profile {profile_id}")
    except Exception as e:
        logger.error(f"Pipeline error for profile {profile_id}: {e}")


@router.patch("/services/{service_id}/location", tags=["Service Management"])
async def update_service_location(
    service_id: int,
    location: LocationUpdate,
    current_admin: User = Depends(deps.get_current_admin),
    db: AsyncSession = Depends(deps.get_db)
):
    """
    Szerviz térképes mozgatása (Koordináta frissítés).
    
    A Nuxt Leaflet térkép drag-and-drop funkciójához használható.
    """
    stmt = select(ServiceProfile).where(ServiceProfile.id == service_id)
    result = await db.execute(stmt)
    profile = result.scalar_one_or_none()
    
    if not profile:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Service profile not found with ID: {service_id}"
        )
    
    # Frissítjük a koordinátákat
    profile.latitude = location.latitude
    profile.longitude = location.longitude
    profile.updated_at = datetime.now()
    
    # Audit log
    audit_log = SecurityAuditLog(
        user_id=current_admin.id,
        action="update_service_location",
        target_service_id=service_id,
        details=f"Service location updated to lat={location.latitude}, lon={location.longitude}",
        is_critical=False,
        ip_address="admin_api"
    )
    db.add(audit_log)
    await db.commit()
    
    return {
        "status": "success",
        "message": f"Service location updated for {service_id}",
        "latitude": location.latitude,
        "longitude": location.longitude
    }


@router.patch("/users/{user_id}/penalty", tags=["Gamification Admin"])
async def apply_gamification_penalty(
    user_id: int,
    penalty: PenaltyRequest,
    current_admin: User = Depends(deps.get_current_admin),
    db: AsyncSession = Depends(deps.get_db)
):
    """
    Gamification büntetés kiosztása egy felhasználónak.
    
    Negatív szintek alkalmazása a frissen létrehozott Gamification rendszerben.
    """
    # Ellenőrizzük, hogy létezik-e a felhasználó
    user_stmt = select(User).where(User.id == user_id)
    user_result = await db.execute(user_stmt)
    user = user_result.scalar_one_or_none()
    
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"User not found with ID: {user_id}"
        )
    
    # Megkeressük a felhasználó gamification profilját (vagy létrehozzuk)
    gamification_stmt = select(UserStats).where(UserStats.user_id == user_id)
    gamification_result = await db.execute(gamification_stmt)
    gamification = gamification_result.scalar_one_or_none()
    
    if not gamification:
        # Ha nincs profil, létrehozzuk alapértelmezett értékekkel
        gamification = UserStats(
            user_id=user_id,
            level=0,
            xp=0,
            reputation_score=100,
            created_at=datetime.now(),
            updated_at=datetime.now()
        )
        db.add(gamification)
        await db.flush()
    
    # Alkalmazzuk a büntetést (negatív szint módosítása)
    # A level mező lehet negatív is a büntetések miatt
    new_level = gamification.level + penalty.penalty_level
    gamification.level = new_level
    gamification.updated_at = datetime.now()
    
    # Audit log
    audit_log = SecurityAuditLog(
        user_id=current_admin.id,
        action="apply_gamification_penalty",
        target_user_id=user_id,
        details=f"Gamification penalty applied: level change {penalty.penalty_level}, reason: {penalty.reason}",
        is_critical=False,
        ip_address="admin_api"
    )
    db.add(audit_log)
    await db.commit()
    
    return {
        "status": "success",
        "message": f"Gamification penalty applied to user {user_id}",
        "user_id": user_id,
        "penalty_level": penalty.penalty_level,
        "new_level": new_level,
        "reason": penalty.reason
    }