"""
Routes pour la gestion des cartes NFC physiques
"""
from fastapi import APIRouter, Depends, HTTPException, Request
from sqlalchemy.orm import Session
from database import get_db
from services.nfc_card_service import NFCCardService
from models.models import User
from core.auth import get_current_user, get_admin_user
from schemas.nfc_card import (
    NFCCardCreate, NFCCardResponse, NFCCardLinkRequest, NFCCardUnlinkRequest,
    NFCCardUpdateRequest, NFCCardTransactionRequest, NFCCardReadRequest,
    NFCCardWriteRequest, NFCCardTransactionResponse, NFCCardBalanceResponse,
    NFCCardListResponse
)
from typing import List
import logging

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

@router.post("/nfc-cards/link", response_model=NFCCardResponse)
async def link_nfc_card(
    request: NFCCardLinkRequest,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Lier une carte NFC à un utilisateur"""
    try:
        card = NFCCardService.link_card_to_user(
            db=db,
            card_uid=request.card_uid,
            card_number=request.card_number,
            user_phone=request.user_phone
        )
        
        logger.info(f"Carte NFC {request.card_uid} liée à l'utilisateur {request.user_phone}")
        return NFCCardResponse.from_orm(card)
        
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        logger.error(f"Erreur liaison carte: {str(e)}")
        raise HTTPException(status_code=500, detail="Erreur lors de la liaison de la carte")

@router.get("/nfc-cards/my-cards", response_model=NFCCardListResponse)
async def get_my_nfc_cards(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Récupérer les cartes NFC de l'utilisateur connecté"""
    try:
        cards = NFCCardService.get_user_cards(db, current_user.id)
        primary_card = next((card for card in cards if card.is_primary), None)
        
        return NFCCardListResponse(
            cards=[NFCCardResponse.from_orm(card) for card in cards],
            total_cards=len(cards),
            primary_card=NFCCardResponse.from_orm(primary_card) if primary_card else None
        )
        
    except Exception as e:
        logger.error(f"Erreur récupération cartes: {str(e)}")
        raise HTTPException(status_code=500, detail="Erreur lors de la récupération des cartes")

@router.get("/nfc-cards/{card_uid}/balance", response_model=NFCCardBalanceResponse)
async def get_card_balance(
    card_uid: str,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Récupérer le solde d'une carte NFC"""
    try:
        card = NFCCardService.get_card_by_uid(db, card_uid)
        if not card:
            raise HTTPException(status_code=404, detail="Carte introuvable")
        
        if card.user_id != current_user.id:
            raise HTTPException(status_code=403, detail="Accès refusé à cette carte")
        
        return NFCCardBalanceResponse(
            card_uid=card.card_uid,
            card_number=card.card_number,
            balance=card.balance,
            max_balance=card.max_balance,
            user_name=current_user.full_name,
            user_phone=current_user.phone,
            last_used_at=card.last_used_at
        )
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Erreur récupération solde: {str(e)}")
        raise HTTPException(status_code=500, detail="Erreur lors de la récupération du solde")

@router.post("/nfc-cards/read", response_model=dict)
async def read_nfc_card(
    request: NFCCardReadRequest,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Lire les données d'une carte NFC"""
    try:
        card_data = NFCCardService.read_card_data(
            db=db,
            card_uid=request.card_uid,
            device_info=request.device_info
        )
        
        # Vérifier que l'utilisateur a accès à cette carte
        if card_data["user_id"] != current_user.id:
            raise HTTPException(status_code=403, detail="Accès refusé à cette carte")
        
        logger.info(f"Données lues de la carte {request.card_uid}")
        return card_data
        
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Erreur lecture carte: {str(e)}")
        raise HTTPException(status_code=500, detail="Erreur lors de la lecture de la carte")

@router.post("/nfc-cards/write", response_model=NFCCardTransactionResponse)
async def write_nfc_card(
    request: NFCCardWriteRequest,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Écrire des données sur une carte NFC"""
    try:
        # Vérifier que l'utilisateur a accès à cette carte
        card = NFCCardService.get_card_by_uid(db, request.card_uid)
        if not card:
            raise HTTPException(status_code=404, detail="Carte introuvable")
        
        if card.user_id != current_user.id:
            raise HTTPException(status_code=403, detail="Accès refusé à cette carte")
        
        card_transaction = NFCCardService.write_card_data(
            db=db,
            card_uid=request.card_uid,
            card_data=request.card_data,
            device_info=request.device_info
        )
        
        logger.info(f"Données écrites sur la carte {request.card_uid}")
        return NFCCardTransactionResponse.from_orm(card_transaction)
        
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Erreur écriture carte: {str(e)}")
        raise HTTPException(status_code=500, detail="Erreur lors de l'écriture sur la carte")

@router.post("/nfc-cards/transaction", response_model=dict)
async def process_nfc_transaction(
    request: NFCCardTransactionRequest,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Traiter une transaction NFC"""
    try:
        # Vérifier que l'utilisateur a accès à cette carte
        card = NFCCardService.get_card_by_uid(db, request.card_uid)
        if not card:
            raise HTTPException(status_code=404, detail="Carte introuvable")
        
        if card.user_id != current_user.id:
            raise HTTPException(status_code=403, detail="Accès refusé à cette carte")
        
        transaction = NFCCardService.process_nfc_transaction(
            db=db,
            card_uid=request.card_uid,
            amount=request.amount,
            transaction_type=request.transaction_type,
            merchant_name=request.merchant_name,
            location=request.location
        )
        
        logger.info(f"Transaction NFC traitée: {transaction.id}")
        return {
            "transaction_id": transaction.id,
            "amount": transaction.amount,
            "type": transaction.transaction_type.value,
            "status": transaction.status.value,
            "reference": transaction.reference
        }
        
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Erreur transaction NFC: {str(e)}")
        raise HTTPException(status_code=500, detail="Erreur lors de la transaction")

@router.put("/nfc-cards/{card_uid}/update", response_model=NFCCardResponse)
async def update_nfc_card(
    card_uid: str,
    request: NFCCardUpdateRequest,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Mettre à jour une carte NFC"""
    try:
        card = NFCCardService.get_card_by_uid(db, card_uid)
        if not card:
            raise HTTPException(status_code=404, detail="Carte introuvable")
        
        if card.user_id != current_user.id:
            raise HTTPException(status_code=403, detail="Accès refusé à cette carte")
        
        # Mettre à jour les champs fournis
        if request.status is not None:
            card.status = request.status
        if request.max_balance is not None:
            card.max_balance = request.max_balance
        if request.is_primary is not None:
            if request.is_primary:
                # Désactiver les autres cartes principales
                db.query(NFCCard).filter(
                    NFCCard.user_id == current_user.id,
                    NFCCard.is_primary == True,
                    NFCCard.id != card.id
                ).update({"is_primary": False})
            card.is_primary = request.is_primary
        
        db.commit()
        db.refresh(card)
        
        logger.info(f"Carte NFC {card_uid} mise à jour")
        return NFCCardResponse.from_orm(card)
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Erreur mise à jour carte: {str(e)}")
        raise HTTPException(status_code=500, detail="Erreur lors de la mise à jour")

@router.delete("/nfc-cards/{card_uid}/unlink")
async def unlink_nfc_card(
    card_uid: str,
    request: NFCCardUnlinkRequest,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Délier une carte NFC"""
    try:
        card = NFCCardService.get_card_by_uid(db, card_uid)
        if not card:
            raise HTTPException(status_code=404, detail="Carte introuvable")
        
        if card.user_id != current_user.id:
            raise HTTPException(status_code=403, detail="Accès refusé à cette carte")
        
        success = NFCCardService.unlink_card(
            db=db,
            card_uid=card_uid,
            reason=request.reason
        )
        
        if success:
            logger.info(f"Carte NFC {card_uid} déliée")
            return {"message": "Carte déliée avec succès"}
        else:
            raise HTTPException(status_code=500, detail="Erreur lors du déliage")
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Erreur déliage carte: {str(e)}")
        raise HTTPException(status_code=500, detail="Erreur lors du déliage")

# Endpoints admin
@router.get("/admin/nfc-cards", response_model=List[NFCCardResponse])
async def get_all_nfc_cards(
    admin_user: User = Depends(get_admin_user),
    db: Session = Depends(get_db)
):
    """Récupérer toutes les cartes NFC (admin uniquement)"""
    try:
        from models.models import NFCCard
        cards = db.query(NFCCard).all()
        return [NFCCardResponse.from_orm(card) for card in cards]
        
    except Exception as e:
        logger.error(f"Erreur récupération cartes admin: {str(e)}")
        raise HTTPException(status_code=500, detail="Erreur lors de la récupération des cartes")
