from __future__ import annotations
import logging
from typing import Optional

from fastapi import APIRouter, Depends, HTTPException, Query, Request, status
from sqlalchemy.orm import Session

from src.apps.auth.utils.auth import get_current_superuser
from src.apps.plan_management.schemas.plan_schemas import (
    PlanCreate,
    PlanUpdate,
    PlanAssignRequest,
    PlanDetailResponse,
    PlanListResponse,
    PlanAssignResponse,
)
from src.apps.plan_management.services import PlanService
from src.apps.plan_management.crud import get_plans
from src.apps.admin.models.admin_audit_log import AdminAuditLog
from src.core.database import get_session
from src.apps.feature_control.services import _get_redis

logger = logging.getLogger(__name__)
router = APIRouter()


@router.get("/plans", response_model=PlanListResponse, tags=["ADMIN_PLANS"])
def list_plans(
    page: int = Query(1, ge=1),
    per_page: int = Query(20, ge=1, le=100),
    is_active: Optional[bool] = Query(None),
    search: Optional[str] = Query(None, max_length=100),
    current_user=Depends(get_current_superuser),
    db: Session = Depends(get_session),
):
    items, total = get_plans(db, page=page, per_page=per_page, is_active=is_active, search=search)
    return {"items": items, "total": total, "page": page, "per_page": per_page}


@router.post("/plans", response_model=PlanDetailResponse, status_code=201, tags=["ADMIN_PLANS"])
def create_plan(
    data: PlanCreate,
    request: Request,
    current_user=Depends(get_current_superuser),
    db: Session = Depends(get_session),
):
    result = PlanService.create_plan(db, data, created_by_user_id=current_user.id)
    AdminAuditLog.log(
        db,
        admin_user_id=current_user.id,
        action="plan.created",
        target_type="plan",
        target_id=result["id"],
        metadata={"plan_name": result["name"]},
        ip_address=request.client.host if request.client else None,
    )
    db.commit()
    return result


@router.get("/plans/{plan_id}", response_model=PlanDetailResponse, tags=["ADMIN_PLANS"])
def get_plan_detail(
    plan_id: int,
    current_user=Depends(get_current_superuser),
    db: Session = Depends(get_session),
):
    return PlanService.get_plan_detail(db, plan_id)


@router.patch("/plans/{plan_id}", response_model=PlanDetailResponse, tags=["ADMIN_PLANS"])
def update_plan(
    plan_id: int,
    data: PlanUpdate,
    request: Request,
    current_user=Depends(get_current_superuser),
    db: Session = Depends(get_session),
    redis_client=Depends(_get_redis),
):
    result = PlanService.update_plan(
        db, plan_id, data,
        updated_by_user_id=current_user.id,
        redis_client=redis_client,
    )
    AdminAuditLog.log(
        db,
        admin_user_id=current_user.id,
        action="plan.updated",
        target_type="plan",
        target_id=plan_id,
        metadata={"plan_name": result["name"]},
        ip_address=request.client.host if request.client else None,
    )
    db.commit()
    return result


@router.delete("/plans/{plan_id}", status_code=204, tags=["ADMIN_PLANS"])
def delete_plan(
    plan_id: int,
    request: Request,
    current_user=Depends(get_current_superuser),
    db: Session = Depends(get_session),
):
    PlanService.delete_plan(db, plan_id)
    AdminAuditLog.log(
        db,
        admin_user_id=current_user.id,
        action="plan.deleted",
        target_type="plan",
        target_id=plan_id,
        ip_address=request.client.host if request.client else None,
    )
    db.commit()


@router.post("/plans/{plan_id}/assign", response_model=PlanAssignResponse, tags=["ADMIN_PLANS"])
def assign_plan(
    plan_id: int,
    data: PlanAssignRequest,
    request: Request,
    current_user=Depends(get_current_superuser),
    db: Session = Depends(get_session),
    redis_client=Depends(_get_redis),
):
    result = PlanService.assign_plan(
        db, plan_id,
        merchant_id=data.merchant_id,
        assigned_by_user_id=current_user.id,
        notes=data.notes,
        redis_client=redis_client,
    )
    AdminAuditLog.log(
        db,
        admin_user_id=current_user.id,
        action="plan.assigned",
        target_type="merchant",
        target_id=data.merchant_id,
        metadata={"plan_id": plan_id},
        ip_address=request.client.host if request.client else None,
    )
    db.commit()
    return result
