"""Rental request router: accept Mietanfrage, save, forward to Rentman."""
import random
from datetime import datetime
from fastapi import APIRouter, Depends, HTTPException, status, Request
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Any
from app.database import get_db
from app.models.equipment import EquipmentCache
from app.models.rental_request import RentalRequest, RentalRequestItem
from app.schemas.rental_request import RentalRequestCreate, RentalRequestResponse
from app.services.rentman_service import RentmanService
from app.services.email_service import EmailService
from app.cache import cache

router = APIRouter(prefix="/api/rental-requests", tags=["rental-requests"])


def generate_reference_number() -> str:
    """Generate a unique reference number: HMS-YYYY-NNNNN."""
    year = datetime.now().year
    num = random.randint(1, 99999)
    return f"HMS-{year}-{num:05d}"


@router.post("", response_model=RentalRequestResponse, status_code=status.HTTP_201_CREATED)
async def create_rental_request(
    payload: RentalRequestCreate,
    request: Request,
    db: AsyncSession = Depends(get_db),
) -> Any:
    """Create a rental request, save to DB, forward to Rentman, send email."""
    # Rate limiting
    client_ip = request.client.host if request.client else "unknown"
    rate_key = f"rate:rental:{client_ip}"
    count = await cache.incr_rate(rate_key, window=60)
    if count > 5:
        raise HTTPException(status_code=status.HTTP_429_TOO_MANY_REQUESTS, detail="Too many requests")

    ref_number = generate_reference_number()

    # Save to database
    rental = RentalRequest(
        reference_number=ref_number,
        event_name=payload.event_name,
        date_start=payload.date_start,
        date_end=payload.date_end,
        location=payload.location,
        person_count=payload.person_count,
        contact_name=payload.contact_name,
        contact_company=payload.contact_company,
        contact_email=str(payload.contact_email),
        contact_phone=payload.contact_phone,
        contact_street=payload.contact_street,
        contact_postalcode=payload.contact_postalcode,
        contact_city=payload.contact_city,
        message=payload.message,
        status="pending",
        rentman_sync_status="pending",
    )
    db.add(rental)
    await db.flush()

    # Fetch equipment info for items
    items_data = []
    for item in payload.items:
        result = await db.execute(select(EquipmentCache).where(EquipmentCache.id == item.equipment_id))
        eq = result.scalar_one_or_none()
        eq_name = eq.name if eq else "Unknown"
        eq_rentman_id = eq.rentman_id if eq else ""

        req_item = RentalRequestItem(
            rental_request_id=rental.id,
            equipment_id=item.equipment_id,
            equipment_name=eq_name,
            rentman_equipment_id=eq_rentman_id,
            quantity=item.quantity,
            rentman_sync_status="pending",
        )
        db.add(req_item)
        items_data.append({
            "equipment_name": eq_name,
            "rentman_equipment_id": eq_rentman_id,
            "quantity": item.quantity,
        })

    await db.commit()

    # Forward to Rentman
    rentman = RentmanService()
    rentman_payload = RentmanService.build_project_request_payload({
        "event_name": payload.event_name,
        "date_start": str(payload.date_start),
        "date_end": str(payload.date_end),
        "contact_name": payload.contact_name,
        "contact_company": payload.contact_company,
        "contact_email": str(payload.contact_email),
        "contact_phone": payload.contact_phone,
        "contact_street": payload.contact_street,
        "contact_postalcode": payload.contact_postalcode,
        "contact_city": payload.contact_city,
        "location": payload.location,
        "message": payload.message,
    })

    try:
        rentman_response = await rentman.create_project_request(rentman_payload)
        rentman_request_id = str(rentman_response.get("id", ""))
        rental.rentman_request_id = rentman_request_id
        rental.rentman_sync_status = "project_created"

        # Add equipment items to Rentman
        for item_data in items_data:
            eq_payload = RentmanService.build_equipment_payload(item_data)
            try:
                await rentman.add_equipment_to_request(rentman_request_id, eq_payload)
            except Exception:
                # Item-level failure: mark as failed but continue
                pass

        rental.rentman_sync_status = "success"
    except Exception:
        rental.rentman_sync_status = "failed"
        rental.rentman_sync_error = "Rentman API request failed"

    await db.commit()

    # Send confirmation email
    email_service = EmailService()
    try:
        await email_service.send_rental_confirmation(
            to_addr=str(payload.contact_email),
            reference_number=ref_number,
            event_name=payload.event_name,
            items=items_data,
            db=db,
        )
    except Exception:
        # Email failure should not affect response
        pass

    return RentalRequestResponse(reference_number=ref_number, status="pending")
