from fastapi import APIRouter, Depends, HTTPException, Query, status
from typing import List, Optional, Dict, Any
from sqlalchemy.orm import Session
from pydantic import BaseModel, EmailStr, Field
from datetime import datetime

from app.api.deps import get_db, get_current_user, get_current_admin_user
from app.models.user import User
from app.services import admin_service
from app.schemas.admin_setting import AdminSettingResponse, AdminSettingUpdate
import logging

router = APIRouter()

# Admin login request model
class AdminLoginRequest(BaseModel):
    username: str
    password: str

@router.post("/login")
def admin_login(
    login_data: AdminLoginRequest,
    db: Session = Depends(get_db)
) -> Any:
    """
    관리자 로그인 엔드포인트.
    
    일반 로그인과 동일하지만 관리자 사용자만 로그인 할 수 있습니다.
    
    Expected JSON body:
    {
        "username": "admin@example.com",
        "password": "admin_password"
    }
    """
    try:
        result = admin_service.authenticate_admin(
            db, 
            email=login_data.username, 
            password=login_data.password
        )
        
        if not result:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Invalid admin credentials",
                headers={"WWW-Authenticate": "Bearer"},
            )
            
        
        logging.info(f"Successful admin login: {login_data.username}")
        return result
        
    except HTTPException:
        raise
    except Exception as e:
        logging.error(f"Admin login failed: {str(e)}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=str(e)
        )

@router.get("/settings", response_model=List[AdminSettingResponse])
def get_all_settings(
    country_code: Optional[str] = Query(None, description="Filter settings by country code"),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_admin_user)
):
    """
    모든 관리자 설정을 조회합니다.
    country_code가 제공되면 해당 국가별 설정만 반환합니다.
    관리자 권한이 필요합니다.
    """
    return admin_service.get_all_settings(db, country_code)

@router.get("/settings/{setting_name}", response_model=AdminSettingResponse)
def get_setting(
    setting_name: str,
    country_code: Optional[str] = Query(None, description="Get setting for specific country"),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_admin_user)
):
    """
    특정 설정을 조회합니다.
    country_code가 제공되면 해당 국가별 설정을 조회합니다.
    관리자 권한이 필요합니다.
    """
    setting = admin_service.get_setting(db, setting_name, country_code)
    if not setting:
        # 설정이 없는 경우 기본값을 가진 응답 생성
        value = admin_service.get_setting_value(db, setting_name, country_code)
        raise HTTPException(
            status_code=404,
            detail=f"Setting '{setting_name}' not found. Default value: {value}"
        )
    return setting

@router.put("/settings/{setting_name}", response_model=AdminSettingResponse)
def update_setting(
    setting_name: str,
    setting_data: AdminSettingUpdate,
    country_code: Optional[str] = Query(None, description="Update setting for specific country"),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_admin_user)
):
    """
    설정을 업데이트합니다.
    country_code가 제공되면 해당 국가별 설정을 업데이트합니다.
    설정이 없는 경우 새로 생성합니다.
    관리자 권한이 필요합니다.
    """
    return admin_service.update_setting(db, setting_name, setting_data, country_code)

@router.get("/settings/default")
def create_default_settings(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_admin_user)
):
    """
    기본 설정 값을 생성합니다. 이미 존재하는 설정은 변경하지 않습니다.
    관리자 권한이 필요합니다.
    """
    admin_service.ensure_default_settings(db)
    return {"message": "Default settings created successfully"}

# 유저 포인트 응답 스키마
class UserPointsInfo(BaseModel):
    user_id: int
    email: str
    first_name: str
    last_name: str
    total_points: int
    updated_at: datetime

@router.get("/user-points", response_model=List[UserPointsInfo])
def get_all_user_points(
    db: Session = Depends(get_db)
):
    """
    모든 사용자의 포인트 정보를 조회합니다.
    
    로그인 여부와 관계없이 접근 가능합니다.
    """
    try:
        user_points = admin_service.get_all_user_points(db)
        return user_points
    except Exception as e:
        logging.error(f"Failed to retrieve user points: {str(e)}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"포인트 정보 조회 중 오류가 발생했습니다: {str(e)}"
        )

# 관리자용 사용자 정보 업데이트 스키마
class AdminUserUpdate(BaseModel):
    first_name: str = Field(..., min_length=2, max_length=50)
    last_name: str = Field(..., min_length=2, max_length=50)
    email: EmailStr
    phone_code: str = Field(..., pattern=r'^\+?[0-9]{1,4}$')
    phone: str = Field(..., pattern=r'^[0-9]{10,15}$')
    gender: str = Field(..., pattern=r'^[MF]$')  # M for Male, F for Female
    birth_date: str = Field(..., pattern=r'^\d{4}-\d{2}-\d{2}$')
    daily_step_goal: int = Field(..., ge=1000, le=100000)
    status: int = Field(..., ge=0, le=1)  # 0: Inactive, 1: Active

# 사용자 정보 업데이트 응답 스키마
class AdminUserUpdateResponse(BaseModel):
    id: int
    email: str
    first_name: str
    last_name: str
    phone_code: str
    phone: str
    gender: str
    birth_date: str
    daily_step_goal: int
    status: int
    updated_at: datetime

@router.put("/users/{user_id}", response_model=AdminUserUpdateResponse)
def update_user_by_admin(
    user_id: int,
    user_data: AdminUserUpdate,
    db: Session = Depends(get_db)
):
    """
    관리자 권한으로 사용자 정보를 업데이트합니다.
    
    로그인 여부와 관계없이 접근 가능합니다.
    """
    try:
        # 요청 데이터를 딕셔너리로 변환
        user_data_dict = user_data.dict()
        
        # 사용자 정보 업데이트
        updated_user = admin_service.update_user_by_admin(db, user_id, user_data_dict)
        return updated_user
    except HTTPException:
        raise
    except Exception as e:
        logging.error(f"Failed to update user: {str(e)}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"사용자 정보 업데이트 중 오류가 발생했습니다: {str(e)}"
        )
    
@router.delete("/product-categories/{category_id}", response_model=Dict[str, Any])
def delete_product_category_endpoint(
    category_id: int,
    db: Session = Depends(get_db)
):
    """
    관리자 권한으로 상품 카테고리를 삭제하는 엔드포인트입니다.
    
    로그인 여부와 관계없이 접근 가능합니다.
    
    제약 조건:
    - 카테고리에 속한 제품이 있는 경우 삭제할 수 없습니다.
    - 관련 제품을 먼저 제거하거나 다른 카테고리로 재할당해야 합니다.
    """
    try:
        result = admin_service.delete_product_category(db, category_id)
        return result
    except HTTPException:
        # 이미 처리된 HTTP 예외는 그대로 전달
        raise
    except Exception as e:
        logging.error(f"Error deleting product category: {str(e)}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"상품 카테고리 삭제 중 오류가 발생했습니다: {str(e)}"
        )

@router.get("/orders", response_model=List[Dict[str, Any]])
def get_all_orders_endpoint(
    skip: int = Query(0, description="건너뛸 레코드 수"),
    limit: int = Query(100, description="최대 조회 레코드 수"),
    db: Session = Depends(get_db)
):
    """
    관리자용 모든 사용자의 주문정보를 조회합니다.
    
    Args:
        skip (int): 건너뛸 레코드 수
        limit (int): 조회할 최대 레코드 수
        db (Session): 데이터베이스 세션
        
    Returns:
        List[Dict]: 모든 주문 정보 목록
    """
    return admin_service.get_all_orders(db, skip, limit)

class OrderStatusUpdate(BaseModel):
    status: str = Field(..., description="주문 상태 (DELIVERED, PROCESSING, PENDING, CANCELLED)")

@router.put("/orders/{order_id}/status", response_model=Dict[str, Any])
def update_order_status_endpoint(
    order_id: int,
    status_update: OrderStatusUpdate,
    db: Session = Depends(get_db)
):
    """
    주문 상태를 업데이트합니다.
    
    Args:
        order_id (int): 업데이트할 주문 ID
        status_update (OrderStatusUpdate): 업데이트할 상태 정보
        db (Session): 데이터베이스 세션
        
    Returns:
        Dict[str, Any]: 업데이트된 주문 정보
    """
    return admin_service.update_order_status(db, order_id, status_update.status)

# 광고 추가/수정 요청 모델
class AdvertisementRequest(BaseModel):
    ad_url: str = Field(..., description="광고 URL")
    video_list_order: int = Field(..., description="광고 비디오 나열 순서", ge=1)
    ad_video_points: int = Field(..., description="광고 비디오 시청 시 지급되는 포인트", ge=0)

@router.post("/advertisements", response_model=Dict[str, Any])
def create_advertisement_endpoint(
    ad_data: AdvertisementRequest,
    db: Session = Depends(get_db)
):
    """
    새로운 광고를 추가합니다.
    
    Args:
        ad_data (AdvertisementRequest): 광고 정보 (ad_url, video_list_order, ad_video_points)
        db (Session): 데이터베이스 세션
        
    Returns:
        Dict[str, Any]: 생성된 광고 정보
    """
    return admin_service.create_advertisement(db, ad_data.dict())

@router.delete("/advertisements/{ad_id}", response_model=Dict[str, Any])
def delete_advertisement_endpoint(
    ad_id: int,
    db: Session = Depends(get_db)
):
    """
    광고를 삭제합니다.
    
    Args:
        ad_id (int): 삭제할 광고 ID
        db (Session): 데이터베이스 세션
        
    Returns:
        Dict[str, Any]: 삭제 결과 메시지
    """
    return admin_service.delete_advertisement(db, ad_id)