"""SQL generation tests for Duckalog."""

from __future__ import annotations

import textwrap

import pytest

from duckalog import (
    Config,
    DuckDBConfig,
    ViewConfig,
    generate_all_views_sql,
    generate_view_sql,
    quote_ident,
    render_options,
)


def test_quote_ident_handles_spaces_and_quotes():
    assert quote_ident('user "events"') == '"user ""events"""'


def test_render_options_renders_supported_types():
    rendered = render_options({"alpha": "one", "beta": True, "gamma": 3.14})
    assert rendered == ", alpha='one', beta=TRUE, gamma=3.14"


def test_generate_view_sql_parquet_with_options():
    view = ViewConfig(
        name="daily users",
        source="parquet",
        uri="s3://bucket/path/*.parquet",
        options={"hive_partitioning": True, "sample_rate": 0.1},
    )

    sql = generate_view_sql(view)

    expected = textwrap.dedent(
        """
        CREATE OR REPLACE VIEW "daily users" AS
        SELECT * FROM parquet_scan('s3://bucket/path/*.parquet', hive_partitioning=TRUE, sample_rate=0.1);
        """
    ).strip()
    assert sql == expected


def test_generate_view_sql_delta_without_options():
    view = ViewConfig(
        name="events_delta",
        source="delta",
        uri="s3://delta/table",
    )

    sql = generate_view_sql(view)

    assert sql.endswith("SELECT * FROM delta_scan('s3://delta/table');")


def test_generate_view_sql_iceberg_uri_and_catalog():
    uri_view = ViewConfig(name="ic_uri", source="iceberg", uri="s3://warehouse/table")

    catalog_view = ViewConfig(
        name="ic_catalog",
        source="iceberg",
        catalog="main",
        table="analytics.orders",
        options={"snapshot_id": 42},
    )

    sql_uri = generate_view_sql(uri_view)
    sql_catalog = generate_view_sql(catalog_view)

    assert "iceberg_scan('s3://warehouse/table')" in sql_uri
    assert "iceberg_scan('main', 'analytics.orders', snapshot_id=42)" in sql_catalog


def test_generate_view_sql_attachment_sources():
    for source in ("duckdb", "sqlite", "postgres"):
        view = ViewConfig(
            name=f"{source}_view", source=source, database="refdb", table="public.users"
        )
        sql = generate_view_sql(view)
        assert sql.endswith("SELECT * FROM refdb.public.users;")


def test_generate_view_sql_raw_sql_preserves_body():
    view = ViewConfig(name="vip", sql="SELECT * FROM base WHERE is_vip")

    sql = generate_view_sql(view)

    assert "SELECT * FROM base WHERE is_vip" in sql
    assert sql.startswith('CREATE OR REPLACE VIEW "vip"')


def test_generate_view_sql_ignores_metadata():
    view = ViewConfig(
        name="meta",
        sql="SELECT 1",
        description="A descriptive view",
        tags=["core", "reporting"],
    )

    sql = generate_view_sql(view)

    expected = textwrap.dedent(
        """
        CREATE OR REPLACE VIEW "meta" AS
        SELECT 1;
        """
    ).strip()
    assert sql.strip() == expected


def test_generate_all_views_sql_header_and_order():
    config = Config(
        version=3,
        duckdb=DuckDBConfig(database="catalog.duckdb"),
        views=[
            ViewConfig(name="first", sql="SELECT 1"),
            ViewConfig(name="second", source="delta", uri="s3://delta/second"),
        ],
    )

    sql = generate_all_views_sql(config)

    expected = textwrap.dedent(
        """
        -- Generated by Duckalog
        -- Config version: 3

        CREATE OR REPLACE VIEW "first" AS
        SELECT 1;

        CREATE OR REPLACE VIEW "second" AS
        SELECT * FROM delta_scan('s3://delta/second');
        """
    ).strip()

    assert sql == expected


def test_render_options_rejects_unsupported_types():
    with pytest.raises(TypeError):
        render_options({"bad": [1, 2, 3]})
