from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File
from sqlalchemy.orm import Session
from typing import Dict, Optional
import os
import uuid
from pathlib import Path
from ..database import get_db
from ..models.site_setting import SiteSetting
from ..models.user import User
from ..schemas.site_setting import SiteSettingCreate, SiteSettingUpdate, SiteSettingResponse, SiteSettingsUpdateBulk, SiteSettingsResponse
from ..auth import get_current_admin_user

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

# File upload configuration
UPLOAD_DIR = Path("uploads/site")
ALLOWED_LOGO_EXTENSIONS = {".png", ".jpg", ".jpeg", ".svg"}
ALLOWED_FAVICON_EXTENSIONS = {".ico", ".png"}
MAX_LOGO_SIZE = 2 * 1024 * 1024  # 2MB
MAX_FAVICON_SIZE = 500 * 1024  # 500KB

# Ensure upload directory exists
UPLOAD_DIR.mkdir(parents=True, exist_ok=True)


def get_setting(db: Session, key: str) -> Optional[str]:
    """Get a single setting value by key."""
    setting = db.query(SiteSetting).filter(SiteSetting.key == key).first()
    return setting.value if setting else None


def get_all_settings_dict(db: Session) -> Dict[str, str]:
    """Get all settings as a dictionary."""
    settings = db.query(SiteSetting).all()
    return {s.key: s.value or "" for s in settings}


@router.get("/public", response_model=SiteSettingsResponse)
async def get_public_settings(db: Session = Depends(get_db)):
    """Get public site settings (no authentication required)."""
    settings_dict = get_all_settings_dict(db)
    return SiteSettingsResponse(
        site_name=settings_dict.get("site_name", "StreamA2026"),
        logo_url=settings_dict.get("logo_url", ""),
        favicon_url=settings_dict.get("favicon_url", ""),
        header_text=settings_dict.get("header_text", "StreamA2026"),
        logo_style=settings_dict.get("logo_style", "")
    )


@router.get("", response_model=SiteSettingsResponse)
async def get_settings(db: Session = Depends(get_db), current_user: User = Depends(get_current_admin_user)):
    """Get all site settings (admin only)."""
    settings_dict = get_all_settings_dict(db)
    return SiteSettingsResponse(
        site_name=settings_dict.get("site_name", "StreamA2026"),
        logo_url=settings_dict.get("logo_url", ""),
        favicon_url=settings_dict.get("favicon_url", ""),
        header_text=settings_dict.get("header_text", "StreamA2026"),
        logo_style=settings_dict.get("logo_style", "")
    )


@router.get("/{key}", response_model=SiteSettingResponse)
async def get_setting_by_key(key: str, db: Session = Depends(get_db), current_user: User = Depends(get_current_admin_user)):
    """Get a single setting by key (admin only)."""
    setting = db.query(SiteSetting).filter(SiteSetting.key == key).first()
    if not setting:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Setting '{key}' not found"
        )
    return setting


@router.put("/{key}", response_model=SiteSettingResponse)
async def update_setting(
    key: str,
    setting_update: SiteSettingUpdate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_admin_user)
):
    """Update a single setting (admin only)."""
    setting = db.query(SiteSetting).filter(SiteSetting.key == key).first()
    if not setting:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Setting '{key}' not found"
        )
    
    setting.value = setting_update.value
    db.commit()
    db.refresh(setting)
    
    return setting


@router.post("/bulk", response_model=SiteSettingsResponse)
async def update_bulk_settings(
    settings_update: SiteSettingsUpdateBulk,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_admin_user)
):
    """Update multiple settings at once (admin only)."""
    settings_dict = get_all_settings_dict(db)
    
    # Update each setting if provided
    if settings_update.site_name is not None:
        setting = db.query(SiteSetting).filter(SiteSetting.key == "site_name").first()
        if setting:
            setting.value = settings_update.site_name
    
    if settings_update.logo_url is not None:
        setting = db.query(SiteSetting).filter(SiteSetting.key == "logo_url").first()
        if setting:
            setting.value = settings_update.logo_url
    
    if settings_update.favicon_url is not None:
        setting = db.query(SiteSetting).filter(SiteSetting.key == "favicon_url").first()
        if setting:
            setting.value = settings_update.favicon_url
    
    if settings_update.header_text is not None:
        setting = db.query(SiteSetting).filter(SiteSetting.key == "header_text").first()
        if setting:
            setting.value = settings_update.header_text
    
    if settings_update.logo_style is not None:
        setting = db.query(SiteSetting).filter(SiteSetting.key == "logo_style").first()
        if not setting:
            setting = SiteSetting(key="logo_style", value=settings_update.logo_style)
            db.add(setting)
        else:
            setting.value = settings_update.logo_style
    
    db.commit()
    
    # Return updated settings
    updated_settings = get_all_settings_dict(db)
    return SiteSettingsResponse(
        site_name=updated_settings.get("site_name", "StreamA2026"),
        logo_url=updated_settings.get("logo_url", ""),
        favicon_url=updated_settings.get("favicon_url", ""),
        header_text=updated_settings.get("header_text", "StreamA2026"),
        logo_style=updated_settings.get("logo_style", "")
    )


@router.post("/upload-logo")
async def upload_logo(
    file: UploadFile = File(...),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_admin_user)
):
    """Upload logo image (admin only)."""
    # Validate file extension
    file_ext = Path(file.filename).suffix.lower()
    if file_ext not in ALLOWED_LOGO_EXTENSIONS:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Invalid file type. Allowed: {', '.join(ALLOWED_LOGO_EXTENSIONS)}"
        )
    
    # Validate file size
    content = await file.read()
    if len(content) > MAX_LOGO_SIZE:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"File too large. Maximum size: {MAX_LOGO_SIZE / 1024 / 1024}MB"
        )
    
    # Generate unique filename
    filename = f"logo_{uuid.uuid4().hex}{file_ext}"
    file_path = UPLOAD_DIR / filename
    
    # Save file
    with open(file_path, "wb") as f:
        f.write(content)
    
    # Update database
    setting = db.query(SiteSetting).filter(SiteSetting.key == "logo_url").first()
    if setting:
        # Delete old logo file if exists
        if setting.value:
            old_path = Path(setting.value)
            if old_path.exists() and old_path.is_relative_to(UPLOAD_DIR):
                old_path.unlink()
        
        setting.value = f"/uploads/site/{filename}"
        db.commit()
    
    return {"logo_url": f"/uploads/site/{filename}"}


@router.post("/upload-favicon")
async def upload_favicon(
    file: UploadFile = File(...),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_admin_user)
):
    """Upload favicon image (admin only)."""
    # Validate file extension
    file_ext = Path(file.filename).suffix.lower()
    if file_ext not in ALLOWED_FAVICON_EXTENSIONS:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Invalid file type. Allowed: {', '.join(ALLOWED_FAVICON_EXTENSIONS)}"
        )
    
    # Validate file size
    content = await file.read()
    if len(content) > MAX_FAVICON_SIZE:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"File too large. Maximum size: {MAX_FAVICON_SIZE / 1024}KB"
        )
    
    # Generate unique filename
    filename = f"favicon_{uuid.uuid4().hex}{file_ext}"
    file_path = UPLOAD_DIR / filename
    
    # Save file
    with open(file_path, "wb") as f:
        f.write(content)
    
    # Update database
    setting = db.query(SiteSetting).filter(SiteSetting.key == "favicon_url").first()
    if setting:
        # Delete old favicon file if exists
        if setting.value:
            old_path = Path(setting.value)
            if old_path.exists() and old_path.is_relative_to(UPLOAD_DIR):
                old_path.unlink()
        
        setting.value = f"/uploads/site/{filename}"
        db.commit()
    
    return {"favicon_url": f"/uploads/site/{filename}"}
