from __future__ import annotations

import pytest
import sqlglot as sg
from pytest import param

import ibis.common.exceptions as com
import ibis.expr.datatypes as dt
from ibis.backends.bigquery.datatypes import BigQueryType


@pytest.mark.parametrize(
    ("datatype", "expected"),
    [
        param(dt.float32, "FLOAT64", id="float32"),
        param(dt.float64, "FLOAT64", id="float64"),
        param(dt.uint8, "INT64", id="uint8"),
        param(dt.uint16, "INT64", id="uint16"),
        param(dt.uint32, "INT64", id="uint32"),
        param(dt.int8, "INT64", id="int8"),
        param(dt.int16, "INT64", id="int16"),
        param(dt.int32, "INT64", id="int32"),
        param(dt.int64, "INT64", id="int64"),
        param(dt.string, "STRING", id="string"),
        param(dt.Array(dt.int64), "ARRAY<INT64>", id="array<int64>"),
        param(dt.Array(dt.string), "ARRAY<STRING>", id="array<string>"),
        param(
            dt.Struct.from_tuples(
                [("a", dt.int64), ("b", dt.string), ("c", dt.Array(dt.string))]
            ),
            "STRUCT<a INT64, b STRING, c ARRAY<STRING>>",
            id="struct",
        ),
        param(dt.date, "DATE", id="date"),
        param(dt.timestamp, "DATETIME", id="datetime"),
        param(
            dt.Timestamp(timezone="UTC"),
            "TIMESTAMP",
            id="timestamp_with_utc_tz",
        ),
        param(
            dt.Timestamp(timezone="US/Eastern"),
            "TIMESTAMP",
            marks=pytest.mark.xfail(
                raises=com.UnsupportedBackendType, reason="Not supported in BigQuery"
            ),
            id="timestamp_with_other_tz",
        ),
        param(
            dt.Array(dt.Struct({"a": dt.string})),
            "ARRAY<STRUCT<a STRING>>",
            id="array<struct>",
        ),
        param(dt.Decimal(38, 9), "NUMERIC", id="decimal-numeric"),
        param(dt.Decimal(76, 38), "BIGNUMERIC", id="decimal-bignumeric"),
        param(
            dt.GeoSpatial(geotype="geography", srid=4326), "GEOGRAPHY", id="geography"
        ),
        param(
            dt.GeoSpatial(geotype="geography"),
            "GEOGRAPHY",
            marks=pytest.mark.xfail(
                raises=com.UnsupportedBackendType,
                reason="Should use the WGS84 reference ellipsoid.",
            ),
            id="geography-no-srid",
        ),
    ],
)
def test_simple(datatype, expected):
    assert BigQueryType.to_string(datatype) == expected


@pytest.mark.parametrize("datatype", [dt.uint64, dt.Decimal(8, 3)])
def test_simple_failure_mode(datatype):
    with pytest.raises(com.UnsupportedBackendType):
        BigQueryType.to_string(datatype)


def test_struct_type():
    dtype = dt.Array(dt.int64)
    parsed_type = sg.parse_one("BIGINT[]", into=sg.exp.DataType, read="duckdb")

    expected = "ARRAY<INT64>"

    assert parsed_type.sql(dialect="bigquery") == expected
    assert BigQueryType.to_string(dtype) == expected
