from fastapi import APIRouter, UploadFile, File, Depends, HTTPException, Form
from typing import List, Dict, Any
from uuid import UUID
from datetime import datetime
from decimal import Decimal

from app.modules.banking.application.parsers.vcb_excel_parser import VCBExcelParser
from app.modules.banking.application.parsers.tcb_pdf_parser import TCBPdfParser
from app.modules.banking.application.parsers.acb_excel_parser import ACBExcelParser
from app.modules.banking.application.parsers.vpbank_excel_parser import VPBankExcelParser
from app.modules.banking.application.reconciliation_engine import ReconciliationEngine
from app.modules.banking.application.commands import RecordTransactionCommand, RecordTransactionCommandHandler, ReconcileTransactionCommand, ReconcileTransactionCommandHandler
from app.core.postgres.base_pkg.base_client import BasePostgresClient
from app.modules.auth.presentation.auth import require_role
from io import BytesIO

router = APIRouter(
    prefix="/v1/erp/banking", 
    tags=["Banking & Reconciliation"],
    dependencies=[Depends(require_role(["superadmin", "director", "accountant", "pm"]))]
)

def get_db_client() -> BasePostgresClient:
    return BasePostgresClient()

@router.post("/upload")
async def upload_statement(
    file: UploadFile = File(...), 
    bank_code: str = Form(None), 
    password: str = Form(None),
    db_client: BasePostgresClient = Depends(get_db_client)
):
    """
    Uploads a bank statement file. Optionally pass bank_code (vcb, tcb, acb, vpbank) and password (for PDF).
    """
    content = await file.read()
    filename_lower = file.filename.lower()
    
    # Auto-detect parser if bank_code not provided
    parser = None
    if bank_code == "tcb" or ("techcombank" in filename_lower or (filename_lower.endswith(".pdf") and "monthly" in filename_lower)):
        parser = TCBPdfParser(password=password)
    elif bank_code == "acb" or "acb" in filename_lower or "saoke" in filename_lower:
        parser = ACBExcelParser()
    elif bank_code == "vpbank" or "vpbank" in filename_lower or "accountstmt" in filename_lower:
        parser = VPBankExcelParser()
    else:
        # Default or fallback
        parser = VCBExcelParser()
        
    try:
        transactions = parser.parse(BytesIO(content), file.filename)
    except Exception as e:
        raise HTTPException(status_code=422, detail=f"Failed to parse statement: {str(e)}")
        
    # Luu vao CSDL thong qua Command
    saved_transactions = []
    record_handler = RecordTransactionCommandHandler(db_client)
    for tx in transactions:
        try:
            cmd = RecordTransactionCommand(
                bank_account_no=tx.get("account_number", "UNKNOWN"),
                amount=Decimal(str(tx.get("credit_amount_vnd", 0) - tx.get("debit_amount_vnd", 0))),
                transaction_date=tx.get("transaction_date", datetime.utcnow()),
                description=tx.get("description", "")
            )
            tx_id = record_handler.handle(cmd)
            tx["id"] = str(tx_id)
            saved_transactions.append(tx)
        except Exception as e:
            print(f"Skipping tx due to error: {e}")
        
    # Chay LLM AI de goi y doi soat (Truy van)
    engine = ReconciliationEngine(db_client=db_client)
    suggested_txs = await engine.suggest_matches(saved_transactions)
    
    return {
        "message": "File processed successfully",
        "file_name": file.filename,
        "total_transactions": len(suggested_txs),
        "transactions": suggested_txs
    }

@router.post("/transactions/{transaction_id}/reconcile")
def reconcile_transaction(
    transaction_id: UUID, 
    payload: Dict[str, Any],
    db_client: BasePostgresClient = Depends(get_db_client)
):
    """
    Xac nhan doi soat giao dich voi Hoa don (CQRS).
    """
    invoice_id = payload.get("invoice_id")
    
    if not invoice_id:
        raise HTTPException(status_code=400, detail="Must provide invoice_id")
        
    command = ReconcileTransactionCommand(
        transaction_id=transaction_id,
        invoice_id=UUID(invoice_id)
    )
    
    handler = ReconcileTransactionCommandHandler(db_client)
    
    try:
        handler.handle(command)
        return {"status": "success", "message": "Giao dịch đã đối soát thành công và Event đã được phát ra."}
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/hot-watcher/scan", summary="Quét và nạp toàn bộ thư mục Hot Watcher (Finance/UNC-2026)")
def scan_hot_watcher(
    db_client: BasePostgresClient = Depends(get_db_client),
) -> Dict[str, Any]:
    """Quét toàn bộ cây thư mục Hot Watcher và tự động nạp các giao dịch mới."""
    from app.modules.banking.application.unc_hot_watcher import UncHotWatcherService
    service = UncHotWatcherService(db_client)
    res = service.scan_all_folders()
    return res


@router.get("/hot-watcher/status", summary="Kiểm tra trạng thái thư mục Hot Watcher")
def get_hot_watcher_status() -> Dict[str, Any]:
    """Kiểm tra đường dẫn và danh sách các thư mục con của Hot Watcher."""
    import os
    from app.modules.banking.application.unc_classifier_and_router import HOT_WATCHER_ROOT, BANK_FOLDER_MAP

    exists = os.path.exists(HOT_WATCHER_ROOT)
    subfolders = {}
    if exists:
        for bank, folder in BANK_FOLDER_MAP.items():
            f_path = os.path.join(HOT_WATCHER_ROOT, folder)
            file_count = len(os.listdir(f_path)) if os.path.exists(f_path) else 0
            subfolders[bank] = {
                "folder": folder,
                "path": f_path,
                "exists": os.path.exists(f_path),
                "file_count": file_count,
            }

    return {
        "hot_watcher_root": HOT_WATCHER_ROOT,
        "exists": exists,
        "banks": subfolders,
        "subfolders": subfolders,
    }



