"""Rentman API client wrapper for equipment import and request submission."""
import httpx
import logging
import re
from typing import Any

from app.config import get_settings

logger = logging.getLogger(__name__)
settings = get_settings()

RENTMAN_BASE_URL = "https://api.rentman.net"


class RentmanService:
    """Wrapper around the Rentman REST API using httpx."""

    def __init__(self, token: str | None = None) -> None:
        self._token = token or settings.rentman_api_token
        self._base_url = RENTMAN_BASE_URL

    def _headers(self) -> dict[str, str]:
        return {
            "Authorization": f"Bearer {self._token}",
            "Content-Type": "application/json",
        }

    async def get_equipment_page(self, limit: int = 100, offset: int = 0) -> dict[str, Any]:
        """Fetch a single page of equipment from Rentman.

        Returns the raw JSON response dict with 'data' and optional 'itemCount'.
        """
        url = f"{self._base_url}/equipment"
        params = {"limit": limit, "offset": offset}
        async with httpx.AsyncClient(timeout=30.0) as client:
            resp = await client.get(url, headers=self._headers(), params=params)
            resp.raise_for_status()
            return resp.json()

    async def get_all_equipment(self, limit: int = 100) -> list[dict[str, Any]]:
        """Paginate through all equipment pages until data is empty."""
        all_items: list[dict[str, Any]] = []
        offset = 0
        while True:
            page = await self.get_equipment_page(limit=limit, offset=offset)
            data = page.get("data", [])
            if not data:
                break
            all_items.extend(data)
            offset += limit
        return all_items

    async def get_file_url(self, file_id: str | int) -> str | None:
        """Fetch the S3 URL for a file from Rentman.

        GET /files/{file_id} → response contains 'url' field with S3 link.
        """
        url = f"{self._base_url}/files/{file_id}"
        try:
            async with httpx.AsyncClient(timeout=30.0) as client:
                resp = await client.get(url, headers=self._headers())
                resp.raise_for_status()
                data = resp.json()
                file_data = data.get("data", data)
                file_url = file_data.get("url")
                if file_url:
                    return file_url
                logger.warning("No url field in file response for file_id=%s", file_id)
                return None
        except Exception as exc:
            logger.warning("Failed to fetch file URL for file_id=%s: %s", file_id, exc)
            return None

    async def transform_equipment(self, raw: dict[str, Any]) -> dict[str, Any]:
        """Map a raw Rentman equipment object to equipment_cache schema.

        Uses 'image' (singular) field which contains a relative path like '/files/3173'.
        Fetches the actual S3 URL via GET /files/{file_id}.
        """
        image_path = raw.get("image")
        image_urls: list[str] = []

        if image_path and isinstance(image_path, str):
            # Extract file_id from path like /files/3173
            match = re.search(r"/files/(\d+)", image_path)
            if match:
                file_id = match.group(1)
                s3_url = await self.get_file_url(file_id)
                if s3_url:
                    image_urls = [s3_url]
            else:
                logger.debug("Could not extract file_id from image path: %s", image_path)

        group = raw.get("equipment_group") or {}
        category = group.get("name", "") if isinstance(group, dict) else str(group or "")

        return {
            "rentman_id": str(raw.get("id", "")),
            "name": raw.get("name", ""),
            "number": raw.get("number") or raw.get("code", ""),
            "category": category,
            "subcategory": raw.get("subcategory", ""),
            "description": raw.get("description", ""),
            "specifications": raw.get("specifications", {}),
            "images": image_urls,
            "rental_price": raw.get("rental_price"),
            "brand": raw.get("brand", ""),
            "available": raw.get("available", True),
            "update_hash": raw.get("updateHash", ""),
        }

    async def create_project_request(self, payload: dict[str, Any]) -> dict[str, Any]:
        """POST /projectrequests to create a new project request in Rentman."""
        url = f"{self._base_url}/projectrequests"
        async with httpx.AsyncClient(timeout=30.0) as client:
            resp = await client.post(url, headers=self._headers(), json=payload)
            resp.raise_for_status()
            return resp.json()

    async def add_equipment_to_request(
        self, request_id: str, equipment_payload: dict[str, Any]
    ) -> dict[str, Any]:
        """POST /projectrequests/{id}/projectrequestequipment for a single item."""
        url = f"{self._base_url}/projectrequests/{request_id}/projectrequestequipment"
        async with httpx.AsyncClient(timeout=30.0) as client:
            resp = await client.post(url, headers=self._headers(), json=equipment_payload)
            resp.raise_for_status()
            return resp.json()

    @staticmethod
    def build_project_request_payload(data: dict[str, Any]) -> dict[str, Any]:
        """Map frontend rental request data to Rentman POST /projectrequests payload."""
        date_start = data.get("date_start")
        date_end = data.get("date_end")

        contact_name = data.get("contact_name", "")
        parts = contact_name.strip().split(" ", 1)
        first_name = parts[0] if parts else ""
        last_name = parts[1] if len(parts) > 1 else ""

        street = data.get("contact_street", "")
        house_number = ""
        if street:
            match = re.search(r"(\d+[a-zA-Z]*)", street)
            if match:
                house_number = match.group(1)

        return {
            "name": data.get("event_name", ""),
            "planperiod_start": f"{date_start}T08:00:00+02:00" if date_start else None,
            "planperiod_end": f"{date_end}T02:00:00+02:00" if date_end else None,
            "usageperiod_start": f"{date_start}T18:00:00+02:00" if date_start else None,
            "usageperiod_end": f"{date_end}T23:59:00+02:00" if date_end else None,
            "contact_name": data.get("contact_company") or data.get("contact_name", ""),
            "contact_person_first_name": first_name,
            "contact_person_lastname": last_name,
            "contact_person_email": data.get("contact_email", ""),
            "contact_person_phone": data.get("contact_phone", ""),
            "location_name": data.get("location", ""),
            "location_mailing_street": street,
            "location_mailing_number": house_number,
            "location_mailing_postalcode": data.get("contact_postalcode", ""),
            "location_mailing_city": data.get("contact_city") or data.get("location", ""),
            "remark": data.get("message", ""),
        }

    @staticmethod
    def build_equipment_payload(item: dict[str, Any]) -> dict[str, Any]:
        """Map a single rental request item to Rentman projectrequestequipment payload."""
        return {
            "name": item.get("equipment_name", ""),
            "quantity": item.get("quantity", 1),
            "quantity_total": item.get("quantity", 1),
            "unit_price": item.get("unit_price", 0),
            "linked_equipment": f"/equipment/{item.get('rentman_equipment_id', '')}" if item.get("rentman_equipment_id") else None,
        }
