"""
Rutas para gestión de empresa
"""

import os
import shutil
from typing import List, Optional
import os
import shutil
from pathlib import Path
from datetime import datetime

from fastapi import APIRouter, Depends, HTTPException, status, File, UploadFile
from fastapi.responses import FileResponse
from sqlalchemy.orm import Session

from core.database import get_core_db
from core.security import get_current_user, validate_access_to_resource
from .....common.tenant_crud_routes import TenantCRUDRoutes
from .dto import CompanyCreateDTO, CompanyResponseDTO, CompanyUpdateDTO
from .models import Company
from .service import CompanyService

# Configuración de directorios
UPLOAD_DIR = "uploads/companies"
ALLOWED_EXTENSIONS = {".jpg", ".jpeg", ".png", ".gif", ".webp"}
MAX_FILE_SIZE = 5 * 1024 * 1024  # 5MB

# Main router that includes base CRUD
router = APIRouter(prefix="/company")


@router.post(
    "",  # Se suma al prefix, queda POST /api/v1/a76/company
    response_model=CompanyResponseDTO,
    status_code=status.HTTP_201_CREATED,
    summary="Create a new company",
)
async def create_company(
    data: CompanyCreateDTO,
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):

    tenant_id = current_user.get("tenant_id")
    if not tenant_id:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Tenant ID not found in user data",
        )

    service = CompanyService(db)
    new_company = service.create_company_manually(data, tenant_id=tenant_id)
    return CompanyResponseDTO.model_validate(service.flatten_company_dto(new_company))


@router.get(
    "",  # GET /api/v1/a76/company with pagination
    response_model=dict,
    summary="Get companies with pagination",
)
async def list_companies(
    page: int = 1,
    page_size: int = 50,
    name: Optional[str] = None,
    rfc: Optional[str] = None,
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):
    """Get paginated list of companies for current tenant with optional filters"""
    tenant_id = current_user.get("tenant_id")
    if not tenant_id:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Tenant ID not found in user data",
        )

    skip = (page - 1) * page_size
    filters = {}
    if name:
        filters["name"] = name
    if rfc:
        filters["rfc"] = rfc

    service = CompanyService(db)
    items, total = service.get_all(
        db,
        tenant_id,
        company_id=0,  # Not used for companies
        skip=skip,
        limit=page_size,
        filters=filters if filters else None,
    )

    total_pages = (total + page_size - 1) // page_size

    return {
        "items": [
            CompanyResponseDTO.model_validate(service.flatten_company_dto(item)) 
            for item in items
        ],
        "total": total,
        "page": page,
        "page_size": page_size,
        "pages": total_pages,
    }


@router.get(
    "/my-companies",
    response_model=List[CompanyResponseDTO],
    summary="Get all companies for current tenant",
)
async def get_my_companies(
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):
    """Get all companies that belong to the current user's tenant"""
    tenant_id = current_user.get("tenant_id")
    if not tenant_id:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Tenant ID not found in user data",
        )

    service = CompanyService(db)
    companies = service.get_companies_by_tenant(tenant_id)

    return [
        CompanyResponseDTO.model_validate(service.flatten_company_dto(company)) 
        for company in companies
    ]

# ... existing code ...

@router.get(
    "/{company_id}",
    response_model=CompanyResponseDTO,
    summary="Get company by ID",
)
async def get_company(
    company_id: int,
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):
    """Get a specific company by ID"""
    tenant_id = current_user.get("tenant_id")
    if not tenant_id:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Tenant ID not found in user data",
        )

    service = CompanyService(db)
    company = CompanyService.get_by_id(db, company_id, tenant_id, 0)
    if not company:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Company not found",
        )

    return CompanyResponseDTO.model_validate(service.flatten_company_dto(company))


@router.put(
    "/{company_id}",
    response_model=CompanyResponseDTO,
    summary="Update company",
)
async def update_company(
    company_id: int,
    data: CompanyUpdateDTO,
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):
    """Update a company"""
    tenant_id = current_user.get("tenant_id")
    if not tenant_id:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Tenant ID not found in user data",
        )

    service = CompanyService(db)
    updated_company = service.update(db, company_id, tenant_id, 0, data)
    if not updated_company:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Company not found",
        )

    return CompanyResponseDTO.model_validate(service.flatten_company_dto(updated_company))








@router.get(
    "/{company_id}/logo/image",
    summary="Get company logo image",
)

async def get_company_logo_image(
    company_id: int,
    db: Session = Depends(get_core_db),
    # Public endpoint to allow <img> tags to load the image without custom headers
):
    """Serve the company logo image file"""
    # Security: In a stricter environment, we would use a signed short-lived URL 
    # or cookie-based auth. For now, checking if company exists is sufficient.
    
    # We find the company ignoring tenant checks for the image serving
    # (Logos are generally considered semi-public assets in this context)
    company = db.query(Company).filter(Company.id == company_id).first()
    
    if not company or not company.logo:
        raise HTTPException(status_code=404, detail="Logo not found")

    file_path = Path(company.logo)
    if not file_path.exists():
        # Fallback for old paths or moved files
        # Check if it exists in the 'standard' location even if DB thinks otherwise
        standard_path = Path(f"app_data/logos/{company_id}") / file_path.name
        if standard_path.exists():
            return FileResponse(standard_path)
            
        raise HTTPException(status_code=404, detail="Logo file not found on server")

    return FileResponse(file_path)


@router.delete(
    "/{company_id}",
    status_code=status.HTTP_204_NO_CONTENT,
    summary="Delete a company",
)
async def delete_company(
    company_id: int,
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):
    """Delete a company"""
    tenant_id = current_user.get("tenant_id")
    if not tenant_id:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Tenant ID not found in user data",
        )

    success = CompanyService.delete(db, company_id, tenant_id, 0)
    if not success:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Company not found",
        )

    return None


@router.post(
    "/{company_id}/upload-logo",
    response_model=dict,
    summary="Upload company logo",
)
async def upload_company_logo(
    company_id: int,
    file: UploadFile = File(...),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):
    """Upload a logo for a company"""
    tenant_id = current_user.get("tenant_id")
    if not tenant_id:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Tenant ID not found in user data",
        )

    # Validar que la empresa existe
    company = CompanyService.get_by_id(db, company_id, tenant_id, 0)
    if not company:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Company not found",
        )

    # Validar extensión
    file_ext = os.path.splitext(file.filename)[1].lower()
    if file_ext not in ALLOWED_EXTENSIONS:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"File type not allowed. Allowed: {', '.join(ALLOWED_EXTENSIONS)}",
        )

    # Validar tamaño
    content = await file.read()
    if len(content) > MAX_FILE_SIZE:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"File too large. Maximum size: {MAX_FILE_SIZE / 1024 / 1024}MB",
        )

    # Crear directorio si no existe
    os.makedirs(UPLOAD_DIR, exist_ok=True)

    # Eliminar logo anterior si existe
    if company.logo:
        old_logo_path = company.logo
        if os.path.exists(old_logo_path):
            try:
                os.remove(old_logo_path)
            except Exception:
                pass  # No es crítico si falla

    # Generar nombre único
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    filename = f"company_{company_id}_{timestamp}{file_ext}"
    file_path = os.path.join(UPLOAD_DIR, filename)

    # Guardar archivo
    try:
        await file.seek(0)
        with open(file_path, "wb") as buffer:
            shutil.copyfileobj(file.file, buffer)
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error saving file: {str(e)}",
        )

    # Actualizar la empresa con la ruta del logo
    update_data = CompanyUpdateDTO(logo=file_path)
    service = CompanyService(db)
    updated_company = service.update(db, company_id, tenant_id, 0, update_data)

    return {
        "message": "Logo uploaded successfully",
        "logo_path": file_path,
        "company_id": company_id,
    }


@router.post(
    "/{company_id}/upload-certificate",
    response_model=dict,
    summary="Upload company certificate",
)
async def upload_company_certificate(
    company_id: int,
    certificate_type: str,
    file: UploadFile = File(...),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):
    """
    Upload a certificate for a company
    certificate_type: fiel_cer, fiel_key, cfdi_cert_cer, cfdi_cert_key, cancel_cer, cancel_key
    """
    tenant_id = current_user.get("tenant_id")
    if not tenant_id:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Tenant ID not found in user data",
        )

    # Validar que la empresa existe
    service = CompanyService(db)
    company = service.get_by_id(db, company_id, tenant_id, 0)
    if not company:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Company not found",
        )
        
    # Validar tipo de certificado
    valid_types = [
        "fiel_cer", "fiel_key", 
        "cfdi_cert_cer", "cfdi_cert_key", 
        "cancel_cer", "cancel_key"
    ]
    if certificate_type not in valid_types:
          raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Invalid certificate type. Allowed: {', '.join(valid_types)}",
        )

    # Validar extensión
    file_ext = os.path.splitext(file.filename)[1].lower()
    allowed_exts = {".cer", ".key"}
    if file_ext not in allowed_exts:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"File type not allowed. Allowed: {', '.join(allowed_exts)}",
        )
        
    # Validar correspondencia extensión vs tipo (simple check)
    if "cer" in certificate_type and file_ext != ".cer":
         raise HTTPException(status_code=400, detail="For this certificate type, file must be .cer")
    if "key" in certificate_type and file_ext != ".key":
         raise HTTPException(status_code=400, detail="For this certificate type, file must be .key")

    # Validar tamaño
    content = await file.read()
    if len(content) > MAX_FILE_SIZE:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"File too large. Maximum size: {MAX_FILE_SIZE / 1024 / 1024}MB",
        )

    # Crear directorio si no existe
    certs_dir = os.path.join(UPLOAD_DIR, str(company_id), "certificates")
    os.makedirs(certs_dir, exist_ok=True)

    # Generar nombre único
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    filename = f"{certificate_type}_{timestamp}{file_ext}"
    file_path = os.path.join(certs_dir, filename)

    # Guardar archivo
    try:
        await file.seek(0)
        with open(file_path, "wb") as buffer:
            shutil.copyfileobj(file.file, buffer)
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error saving file: {str(e)}",
        )

    # Actualizar la base de datos
    service.upload_certificate(company_id, certificate_type, file_path, tenant_id)

    return {
        "message": "Certificate uploaded successfully",
        "file_path": file_path,
        "certificate_type": certificate_type,
        "company_id": company_id,
    }
