"""Google Sheets API v4 integration via raw httpx."""

import httpx

from fliiq.runtime.google_auth import get_access_token

BASE_URL = "https://sheets.googleapis.com/v4/spreadsheets"


async def handler(params: dict) -> dict:
    """Handle Google Sheets operations."""
    action = params["action"]

    try:
        _, access_token = await get_access_token(params.get("account_email"))
        headers = {
            "Authorization": f"Bearer {access_token}",
            "Content-Type": "application/json",
        }

        async with httpx.AsyncClient(timeout=30) as client:
            if action == "create":
                return await _create(client, headers, params)
            elif action == "get_metadata":
                return await _get_metadata(client, headers, params)
            elif action == "read_range":
                return await _read_range(client, headers, params)
            elif action == "write_range":
                return await _write_range(client, headers, params)
            elif action == "append_rows":
                return await _append_rows(client, headers, params)
            else:
                return {
                    "success": False,
                    "message": f"Unknown action: {action}",
                    "data": {},
                }
    except ValueError:
        raise
    except httpx.HTTPStatusError as e:
        error_msg = f"Google Sheets API error: {e.response.status_code}"
        try:
            error_data = e.response.json()
            if "error" in error_data:
                detail = error_data["error"]
                if isinstance(detail, dict):
                    error_msg += f" - {detail.get('message', '')}"
                else:
                    error_msg += f" - {detail}"
        except Exception:
            pass
        return {"success": False, "message": error_msg, "data": {}}
    except Exception as e:
        return {"success": False, "message": f"Error: {e}", "data": {}}


async def _create(
    client: httpx.AsyncClient, headers: dict, params: dict
) -> dict:
    """Create a new spreadsheet."""
    title = params.get("title", "Untitled Spreadsheet")

    resp = await client.post(
        BASE_URL,
        headers=headers,
        json={"properties": {"title": title}},
    )
    resp.raise_for_status()

    data = resp.json()
    return {
        "success": True,
        "message": f"Created spreadsheet '{title}'",
        "data": {
            "spreadsheet_id": data["spreadsheetId"],
            "title": data["properties"]["title"],
            "url": data.get("spreadsheetUrl", ""),
        },
    }


async def _get_metadata(
    client: httpx.AsyncClient, headers: dict, params: dict
) -> dict:
    """Get spreadsheet metadata."""
    spreadsheet_id = params.get("spreadsheet_id")
    if not spreadsheet_id:
        return {
            "success": False,
            "message": "spreadsheet_id is required for get_metadata",
            "data": {},
        }

    resp = await client.get(
        f"{BASE_URL}/{spreadsheet_id}",
        headers=headers,
    )
    resp.raise_for_status()

    data = resp.json()
    sheets = [
        {
            "title": s["properties"]["title"],
            "sheet_id": s["properties"]["sheetId"],
            "row_count": s["properties"].get("gridProperties", {}).get("rowCount"),
            "column_count": s["properties"].get("gridProperties", {}).get("columnCount"),
        }
        for s in data.get("sheets", [])
    ]

    return {
        "success": True,
        "message": f"Spreadsheet '{data['properties']['title']}' has {len(sheets)} sheet(s)",
        "data": {
            "spreadsheet_id": data["spreadsheetId"],
            "title": data["properties"]["title"],
            "sheets": sheets,
            "url": data.get("spreadsheetUrl", ""),
        },
    }


async def _read_range(
    client: httpx.AsyncClient, headers: dict, params: dict
) -> dict:
    """Read values from a cell range."""
    spreadsheet_id = params.get("spreadsheet_id")
    cell_range = params.get("range")
    if not spreadsheet_id or not cell_range:
        return {
            "success": False,
            "message": "spreadsheet_id and range are required for read_range",
            "data": {},
        }

    resp = await client.get(
        f"{BASE_URL}/{spreadsheet_id}/values/{cell_range}",
        headers=headers,
    )
    resp.raise_for_status()

    data = resp.json()
    values = data.get("values", [])
    return {
        "success": True,
        "message": f"Read {len(values)} row(s) from {cell_range}",
        "data": {"range": data.get("range", cell_range), "values": values},
    }


async def _write_range(
    client: httpx.AsyncClient, headers: dict, params: dict
) -> dict:
    """Write values to a cell range."""
    spreadsheet_id = params.get("spreadsheet_id")
    cell_range = params.get("range")
    values = params.get("values")
    if not spreadsheet_id or not cell_range or values is None:
        return {
            "success": False,
            "message": "spreadsheet_id, range, and values are required for write_range",
            "data": {},
        }

    value_input = params.get("value_input_option", "USER_ENTERED")

    resp = await client.put(
        f"{BASE_URL}/{spreadsheet_id}/values/{cell_range}",
        headers=headers,
        params={"valueInputOption": value_input},
        json={"values": values},
    )
    resp.raise_for_status()

    data = resp.json()
    return {
        "success": True,
        "message": f"Updated {data.get('updatedCells', 0)} cell(s) in {cell_range}",
        "data": {
            "updated_range": data.get("updatedRange", ""),
            "updated_rows": data.get("updatedRows", 0),
            "updated_columns": data.get("updatedColumns", 0),
            "updated_cells": data.get("updatedCells", 0),
        },
    }


async def _append_rows(
    client: httpx.AsyncClient, headers: dict, params: dict
) -> dict:
    """Append rows after existing data."""
    spreadsheet_id = params.get("spreadsheet_id")
    cell_range = params.get("range")
    values = params.get("values")
    if not spreadsheet_id or not cell_range or values is None:
        return {
            "success": False,
            "message": "spreadsheet_id, range, and values are required for append_rows",
            "data": {},
        }

    value_input = params.get("value_input_option", "USER_ENTERED")

    resp = await client.post(
        f"{BASE_URL}/{spreadsheet_id}/values/{cell_range}:append",
        headers=headers,
        params={
            "valueInputOption": value_input,
            "insertDataOption": "INSERT_ROWS",
        },
        json={"values": values},
    )
    resp.raise_for_status()

    data = resp.json()
    updates = data.get("updates", {})
    return {
        "success": True,
        "message": f"Appended {updates.get('updatedRows', 0)} row(s)",
        "data": {
            "updated_range": updates.get("updatedRange", ""),
            "updated_rows": updates.get("updatedRows", 0),
            "updated_cells": updates.get("updatedCells", 0),
        },
    }
