"""Tests for Rentman request submission pipeline (T04)."""
import pytest
from unittest.mock import AsyncMock, patch, MagicMock
from app.services.rentman_service import RentmanService


def test_build_project_request_payload():
    data = {
        "event_name": "Sommerfest 2026",
        "date_start": "2026-08-15",
        "date_end": "2026-08-16",
        "contact_name": "Max Mustermann",
        "contact_company": "Firma GmbH",
        "contact_email": "max@example.com",
        "contact_phone": "+49 170 1234567",
        "contact_street": "Hauptstr. 42a",
        "contact_postalcode": "80000",
        "contact_city": "Muenchen",
        "location": "Muenchen",
        "message": "Brauchen PA",
    }
    payload = RentmanService.build_project_request_payload(data)
    assert payload["name"] == "Sommerfest 2026"
    assert payload["planperiod_start"] == "2026-08-15T08:00:00+02:00"
    assert payload["planperiod_end"] == "2026-08-16T02:00:00+02:00"
    assert payload["usageperiod_start"] == "2026-08-15T18:00:00+02:00"
    assert payload["usageperiod_end"] == "2026-08-16T23:59:00+02:00"
    assert payload["contact_name"] == "Firma GmbH"
    assert payload["contact_person_first_name"] == "Max"
    assert payload["contact_person_lastname"] == "Mustermann"
    assert payload["contact_person_email"] == "max@example.com"
    assert payload["location_mailing_street"] == "Hauptstr. 42a"
    assert payload["location_mailing_number"] == "42a"
    assert payload["location_mailing_postalcode"] == "80000"
    assert payload["location_mailing_city"] == "Muenchen"
    assert payload["remark"] == "Brauchen PA"


def test_build_project_request_payload_no_company():
    """When no company, contact_name should use contact_name."""
    data = {
        "event_name": "Test",
        "date_start": "2026-08-15",
        "date_end": "2026-08-16",
        "contact_name": "Anna Schmidt",
        "contact_company": None,
        "contact_email": "anna@example.com",
        "contact_street": "Testweg 5",
        "contact_postalcode": "10000",
        "contact_city": "Berlin",
        "location": "Berlin",
    }
    payload = RentmanService.build_project_request_payload(data)
    assert payload["contact_name"] == "Anna Schmidt"
    assert payload["contact_person_first_name"] == "Anna"
    assert payload["contact_person_lastname"] == "Schmidt"
    assert payload["location_mailing_number"] == "5"


def test_build_equipment_payload():
    item = {
        "equipment_name": "L-Acoustics K2",
        "rentman_equipment_id": "101",
        "quantity": 4,
        "unit_price": 150.00,
    }
    payload = RentmanService.build_equipment_payload(item)
    assert payload["name"] == "L-Acoustics K2"
    assert payload["quantity"] == 4
    assert payload["quantity_total"] == 4
    assert payload["unit_price"] == 150.00
    assert payload["linked_equipment"] == "/equipment/101"


@pytest.mark.asyncio
async def test_projectrequest_success():
    """Mock Rentman API: create project request returns ID, equipment added."""
    svc = RentmanService(token="test-token")
    svc.create_project_request = AsyncMock(return_value={"id": "9999", "name": "Test Event"})
    svc.add_equipment_to_request = AsyncMock(return_value={"id": "equip-1"})

    project_payload = {"name": "Test Event", "usageperiod_start": "2026-08-15T18:00:00+02:00"}
    result = await svc.create_project_request(project_payload)
    assert result["id"] == "9999"

    equip_payload = {"name": "K2", "quantity": 2}
    eq_result = await svc.add_equipment_to_request("9999", equip_payload)
    assert eq_result["id"] == "equip-1"


@pytest.mark.asyncio
async def test_equipment_retry():
    """Failed equipment POST should be retried (exponential backoff simulation)."""
    svc = RentmanService(token="test-token")
    call_count = 0

    async def mock_add(*args, **kwargs):
        nonlocal call_count
        call_count += 1
        if call_count < 3:
            raise Exception("Temporary failure")
        return {"id": "success"}

    svc.add_equipment_to_request = mock_add

    # Simulate retry logic
    max_retries = 3
    result = None
    for attempt in range(max_retries):
        try:
            result = await svc.add_equipment_to_request("1", {"name": "test"})
            break
        except Exception:
            if attempt == max_retries - 1:
                raise
            import asyncio
            await asyncio.sleep(0.01 * (2 ** attempt))

    assert result == {"id": "success"}
    assert call_count == 3
