"""Unit tests for the Alteryx → DuckDB expression transpiler."""
from __future__ import annotations
import sys
from pathlib import Path
import pytest

PKG = Path(__file__).parent.parent  # alteryx_runner/
if str(PKG) not in sys.path:
    sys.path.insert(0, str(PKG))

from expression.transpiler import transpile, UnsupportedExpressionError


def t(expr: str) -> str:
    return transpile(expr)


class TestLiterals:
    def test_number(self):
        assert t("42") == "42"

    def test_float(self):
        assert t("3.14") == "3.14"

    def test_string(self):
        assert t('"hello"') == "'hello'"

    def test_null(self):
        assert t("NULL()") == "NULL"

    def test_true(self):
        assert t("True") == "TRUE"

    def test_false(self):
        assert t("False") == "FALSE"


class TestColumnRef:
    def test_simple(self):
        assert t("[CustomerID]") == '"CustomerID"'

    def test_spaces(self):
        assert t("[First Name]") == '"First Name"'


class TestOperators:
    def test_eq(self):
        assert t("[A] == [B]") == '("A" = "B")'

    def test_neq(self):
        assert t("[A] != [B]") == '("A" <> "B")'

    def test_gt(self):
        assert t("[Score] > 50") == '("Score" > 50)'

    def test_and(self):
        sql = t('[A] > 0 AND [B] < 10')
        assert "AND" in sql

    def test_or(self):
        sql = t('[A] > 0 OR [B] < 0')
        assert "OR" in sql

    def test_not(self):
        sql = t('NOT [IsActive]')
        assert "NOT" in sql

    def test_bang(self):
        sql = t('![IsActive]')
        assert "NOT" in sql


class TestIfThenEndif:
    def test_simple(self):
        sql = t('IF [Score] > 50 THEN "Pass" ELSE "Fail" ENDIF')
        assert "CASE WHEN" in sql
        assert "'Pass'" in sql
        assert "'Fail'" in sql

    def test_elseif(self):
        sql = t('IF [Score] > 90 THEN "A" ELSEIF [Score] > 70 THEN "B" ELSE "C" ENDIF')
        assert sql.count("WHEN") == 2

    def test_no_else(self):
        sql = t('IF [Active] == "Y" THEN "Yes" ENDIF')
        assert "CASE WHEN" in sql


class TestIIF:
    def test_iif(self):
        sql = t('IIF([Score] > 50, "Pass", "Fail")')
        assert "CASE WHEN" in sql


class TestIsNull:
    def test_isnull_keyword(self):
        sql = t('IsNull([Field])')
        assert "IS NULL" in sql

    def test_not_isnull(self):
        sql = t('!IsNull([Field])')
        assert "NOT" in sql and "IS NULL" in sql


class TestFunctions:
    def test_uppercase(self):
        assert t('Uppercase([Name])') == "UPPER(\"Name\")"

    def test_length(self):
        assert "LENGTH" in t('Length([Name])')

    def test_left(self):
        assert "LEFT" in t('Left([Name], 3)')

    def test_round(self):
        assert "ROUND" in t('Round([Score], 2)')

    def test_abs(self):
        assert "ABS" in t('ABS([Val])')

    def test_trim(self):
        assert "TRIM" in t('Trim([Name])')

    def test_nested(self):
        sql = t('Uppercase(Trim([Name]))')
        assert "UPPER" in sql
        assert "TRIM" in sql


class TestArithmetic:
    def test_add(self):
        sql = t('[A] + [B]')
        assert "+" in sql

    def test_multiply(self):
        sql = t('[A] * [B]')
        assert "*" in sql

    def test_divide(self):
        sql = t('[A] / [B]')
        assert "/" in sql

    def test_complex(self):
        sql = t('ROUND([Spend] / [Visits], 1)')
        assert "ROUND" in sql


class TestDateFunctions:
    def test_datetimenow(self):
        sql = t('DateTimeNow()')
        assert "NOW()" in sql

    def test_datetimetoday(self):
        sql = t('DateTimeToday()')
        assert "CURRENT_DATE" in sql
