"""
Card import router endpoints.

Provides endpoints for importing card collections from files,
viewing import status, and confirming imports.
"""
import json
from typing import List, Optional, Dict, Any
from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from sqlalchemy.orm import selectinload
from datetime import datetime

from app.core.database import get_db
from app.core.security import get_current_user
from app.models.card_import_batch import CardImportBatch
from app.models.user_card_import_record import UserCardImportRecord
from app.models.user_data import UserCardCollection
from app.models.models import MtgonlineCard
from app.models.user_deck import UserDeck, UserDeckCard
from app.services.file_parser import FileParser
from app.services.import_batch_processor import ImportBatchProcessor
from app.services.fuzzy_card_matcher import FuzzyCardMatcher
from app.schemas.card_import_schemas import (
    CardImportRequest,
    CardImportResponse,
    CardImportStatusResponse,
    CardMatchResult,
    CardImportSummary,
)
from app.schemas.generic_schemas import MessageResponse
from app.schemas.user_deck_schemas import DeckCardResponse, DeckCardListResponse

router = APIRouter()


@router.post("/import", response_model=CardImportResponse, status_code=status.HTTP_201_CREATED)
async def upload_card_import(
    file: UploadFile = File(...),
    db: AsyncSession = Depends(get_db),
    current_user: dict = Depends(get_current_user),
):
    """
    Upload a card import file (XLSX, CSV, JSON, ODS).
    
    Parses the file, performs fuzzy matching, and creates an import batch.
    """
    user_id = int(current_user["user_id"])

    # Validate file type
    if not file.filename:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="File must have a filename"
        )

    file_type = file.filename.split(".")[-1].lower()
    supported_types = ["xlsx", "csv", "json", "ods"]
    if file_type not in supported_types:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Unsupported file type: {file_type}. Supported types: {supported_types}"
        )

    # Read file content
    content = await file.read()
    file_size = len(content)

    # Parse file
    from pathlib import Path
    import tempfile

    with tempfile.NamedTemporaryFile(suffix=f".{file_type}", delete=False) as tmp_file:
        tmp_file.write(content)
        tmp_file_path = Path(tmp_file.name)

    try:
        card_names = await FileParser.parse_file(tmp_file_path)
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Failed to parse file: {str(e)}"
        )

    if not card_names:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="File contains no card names"
        )

    # Create import batch
    batch = await ImportBatchProcessor.create_batch(
        db=db,
        user_id=user_id,
        filename=file.filename,
        file_type=file_type,
        file_size=file_size,
        card_names=card_names,
    )

    # Process batch
    result = await ImportBatchProcessor.process_batch(
        db=db,
        batch=batch,
        card_names=card_names,
    )

    return CardImportResponse(
        message=f"Import batch created successfully",
        batch_id=batch.id,
        card_count=len(card_names),
        status=result["status"],
        imported_at=datetime.utcnow(),
    )


@router.get("/import/{import_id}/status", response_model=CardImportStatusResponse)
async def get_import_status(
    import_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: dict = Depends(get_current_user),
):
    """Get the status of an import batch."""
    user_id = int(current_user["user_id"])

    batch = await ImportBatchProcessor.get_batch_status(db, import_id)
    if not batch:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Import batch {import_id} not found"
        )

    if batch.user_id != user_id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Access denied"
        )

    return CardImportStatusResponse(
        has_import=True,
        batch_id=batch.id,
        status=batch.status,
        card_count=batch.total_cards,
        matched_count=batch.matched_cards,
        unmatched_count=batch.unmatched_cards,
        last_imported=batch.updated_at,
        error_message=batch.error_message,
    )


@router.get("/import/{import_id}/results", response_model=CardImportSummary)
async def get_import_results(
    import_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: dict = Depends(get_current_user),
):
    """Get the match results for an import batch."""
    user_id = int(current_user["user_id"])

    batch = await ImportBatchProcessor.get_batch_status(db, import_id)
    if not batch:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Import batch {import_id} not found"
        )

    if batch.user_id != user_id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Access denied"
        )

    if batch.status != "completed":
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Import batch {import_id} has not completed yet (status: {batch.status})"
        )

    match_results = batch.match_results or []

    matched_cards = []
    unmatched_cards = []

    for original_name, card_id, matched_name, confidence, match_type in match_results:
        if matched_name:
            matched_cards.append(CardMatchResult(
                card_id=card_id,
                card_name=original_name,
                matched_name=matched_name,
                match_type=match_type,
                confidence=confidence,
            ))
        else:
            unmatched_cards.append(original_name)

    return CardImportSummary(
        total_cards=len(match_results),
        matched_cards=matched_cards,
        unmatched_cards=unmatched_cards,
        import_id=batch.id,
    )


@router.post("/import/{import_id}/confirm", response_model=MessageResponse)
async def confirm_import(
    import_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: dict = Depends(get_current_user),
):
    """Confirm an import batch and save to user's card collection."""
    user_id = int(current_user["user_id"])

    batch = await ImportBatchProcessor.get_batch_status(db, import_id)
    if not batch:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Import batch {import_id} not found"
        )

    if batch.user_id != user_id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Access denied"
        )

    if batch.status != "completed":
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Import batch {import_id} has not completed yet (status: {batch.status})"
        )

    # Confirm batch
    try:
        await ImportBatchProcessor.confirm_batch(db, import_id, user_id)
    except ValueError as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )

    # Save matched cards to user's collection
    match_results = batch.match_results or []
    saved_count = 0

    for original_name, card_id, matched_name, confidence, match_type in match_results:
        if card_id and match_type in ["exact", "high_confidence"]:
            # Check if already in collection
            stmt = select(UserCardCollection).where(
                UserCardCollection.user_id == user_id,
                UserCardCollection.card_id == card_id,
            )
            result = await db.execute(stmt)
            existing = result.scalar_one_or_none()

            if existing:
                existing.quantity += 1
            else:
                new_collection = UserCardCollection(
                    user_id=user_id,
                    card_id=card_id,
                    quantity=1,
                )
                db.add(new_collection)
            saved_count += 1

    await db.flush()

    return MessageResponse(
        message=f"Import confirmed. {saved_count} cards added to your collection."
    )


@router.get("/user/cards", response_model=List[Dict[str, Any]])
async def get_user_cards(
    db: AsyncSession = Depends(get_db),
    current_user: dict = Depends(get_current_user),
):
    """List user's imported cards."""
    user_id = int(current_user["user_id"])

    stmt = select(UserCardCollection).where(UserCardCollection.user_id == user_id).order_by(UserCardCollection.created_at.desc())
    result = await db.execute(stmt)
    collections = result.scalars().all()

    # Fetch card details
    card_ids = [c.card_id for c in collections]
    card_details = {}
    if card_ids:
        card_stmt = select(MtgonlineCard).where(MtgonlineCard.id.in_(card_ids))
        card_result = await db.execute(card_stmt)
        for card in card_result.scalars().all():
            card_details[card.id] = card

    result_list = []
    for collection in collections:
        card = card_details.get(collection.card_id)
        result_list.append({
            "collection_id": collection.id,
            "card_id": collection.card_id,
            "card_name": card.name if card else f"Card#{collection.card_id}",
            "card_type_line": card.type_line if card else "",
            "quantity": collection.quantity,
            "condition": collection.condition,
            "language": collection.language,
            "is_foil": collection.is_foil,
            "is_alt_art": collection.is_alt_art,
            "acquired_date": collection.acquired_date,
        })

    return result_list


@router.delete("/user/cards/{card_import_id}", response_model=MessageResponse)
async def delete_user_card(
    card_import_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: dict = Depends(get_current_user),
):
    """Remove a card from user's collection."""
    user_id = int(current_user["user_id"])

    stmt = select(UserCardCollection).where(
        UserCardCollection.id == card_import_id,
        UserCardCollection.user_id == user_id,
    )
    result = await db.execute(stmt)
    collection = result.scalar_one_or_none()

    if not collection:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Card not found in your collection"
        )

    await db.delete(collection)
    await db.flush()

    return MessageResponse(message="Card removed from your collection")


@router.get("/user/decks", response_model=List[Dict[str, Any]])
async def get_user_decks(
    db: AsyncSession = Depends(get_db),
    current_user: dict = Depends(get_current_user),
):
    """List user's decks."""
    user_id = int(current_user["user_id"])

    stmt = select(UserDeck).where(UserDeck.user_id == user_id).order_by(UserDeck.updated_at.desc())
    result = await db.execute(stmt)
    decks = result.scalars().all()

    result_list = []
    for deck in decks:
        result_list.append({
            "deck_id": deck.id,
            "name": deck.name,
            "status": deck.status,
            "format": deck.format,
            "folder_id": deck.folder_id,
            "notes": deck.notes,
            "is_precedent": deck.is_precedent,
            "created_at": deck.created_at,
            "updated_at": deck.updated_at,
        })

    return result_list
