///|
pub(all) struct Postgres {}

///|
pub impl Dialect for Postgres with supports_string_literal_backslash_escape(
  _self,
) {
  false
}

///|
pub impl Dialect for Postgres with supports_boolean_literals(_self) {
  true
}

///|
pub impl Dialect for Postgres with supports_filter_during_aggregation(_self) {
  true
}

///|
pub impl Dialect for Postgres with supports_within_after_array_aggregation(
  _self,
) {
  true
}

///|
pub impl Dialect for Postgres with supports_double_quoted_identifiers(_self) {
  true
}

///|
pub impl Dialect for Postgres with supports_array_syntax(_self) {
  true
}

///|
pub impl Dialect for Postgres with supports_if_not_exists(_self) {
  true
}

///|
pub impl Dialect for Postgres with requires_column_types_in_create_table(_self) {
  true
}

///|
pub impl Dialect for Postgres with parse_statement(
  _self : Postgres,
  _parser : Parser,
  tokens : ArrayView[Token],
) -> ParserResult[Statement]? raise ParserError {
  match tokens {
    [Keyword(Listen), Identifier(channel), Semicolon, .. rest] =>
      // PostgreSQL LISTEN statement
      Some((Statement::Listen(channel), rest))
    [Keyword(Notify), Identifier(channel), Semicolon, .. rest] =>
      // PostgreSQL NOTIFY statement without payload
      Some((Statement::Notify(channel, None), rest))
    [
      Keyword(Notify),
      Identifier(channel),
      Comma,
      StringLiteral(payload),
      Semicolon,
      .. rest,
    ] =>
      // PostgreSQL NOTIFY statement with payload
      Some((Statement::Notify(channel, Some(payload)), rest))
    _ => None // Fall back to generic parsing
  }
}

///|
pub impl Dialect for Postgres with parse_expr(
  _self : Postgres,
  tokens : ArrayView[Token],
) -> ParserResult[Expr]? raise ParserError {
  match tokens {
    [Keyword(Array), LBracket, .. _tokens] =>
      // PostgreSQL ARRAY[...] syntax - delegate to parser
      None // Let the main parser handle this
    [LBracket, .. _tokens] =>
      // PostgreSQL bracket array syntax [1, 2, 3] - delegate to parser  
      None // Let the main parser handle this
    _ => None
  }
}

///|
test "PostgreSQL LISTEN" {
  let tokens = "LISTEN my_channel;"
  let stmt = parse_sql(dialect=Postgres::{  }, tokens).stmts[0] |> pretty_print
  inspect(
    stmt,
    content=(
      #|LISTEN my_channel;
    ),
  )
}

///|
test "PostgreSQL NOTIFY without payload" {
  let tokens = "NOTIFY my_channel;"
  let stmt = parse_sql(dialect=Postgres::{  }, tokens).stmts[0] |> pretty_print
  inspect(
    stmt,
    content=(
      #|NOTIFY my_channel;
    ),
  )
}

///|
test "PostgreSQL NOTIFY with payload" {
  let tokens = "NOTIFY my_channel, 'hello world';"
  let stmt = parse_sql(dialect=Postgres::{  }, tokens).stmts[0] |> pretty_print
  inspect(
    stmt,
    content=(
      #|NOTIFY my_channel, 'hello world';
    ),
  )
}

///|
// PostgreSQL array syntax tests

test "PostgreSQL ARRAY syntax with integers" {
  let tokens = "SELECT ARRAY[1, 2, 3, 4] FROM test;"
  let stmt = parse_sql(dialect=Postgres::{  }, tokens).stmts[0] |> pretty_print
  inspect(
    stmt,
    content=(
      #|SELECT
      #|  ARRAY[1, 2, 3, 4]
      #|FROM
      #|  test;
    ),
  )
}

///|
test "PostgreSQL bracket array syntax" {
  let tokens = "SELECT [1, 2, 3] FROM test;"
  let stmt = parse_sql(dialect=Postgres::{  }, tokens).stmts[0] |> pretty_print
  inspect(
    stmt,
    content=(
      #|SELECT
      #|  [1, 2, 3]
      #|FROM
      #|  test;
    ),
  )
}

///|
test "PostgreSQL empty ARRAY" {
  let tokens = "SELECT ARRAY[] FROM test;"
  let stmt = parse_sql(dialect=Postgres::{  }, tokens).stmts[0] |> pretty_print
  inspect(
    stmt,
    content=(
      #|SELECT
      #|  ARRAY[]
      #|FROM
      #|  test;
    ),
  )
}

///|
test "PostgreSQL ARRAY with strings" {
  let tokens = "SELECT ARRAY['hello', 'world'] FROM test;"
  let stmt = parse_sql(dialect=Postgres::{  }, tokens).stmts[0] |> pretty_print
  inspect(
    stmt,
    content=(
      #|SELECT
      #|  ARRAY['hello', 'world']
      #|FROM
      #|  test;
    ),
  )
}

///|
test "PostgreSQL nested arrays" {
  let tokens = "SELECT ARRAY[ARRAY[1, 2], ARRAY[3, 4]] FROM test;"
  let stmt = parse_sql(dialect=Postgres::{  }, tokens).stmts[0] |> pretty_print
  inspect(
    stmt,
    content=(
      #|SELECT
      #|  ARRAY[ARRAY[1, 2], ARRAY[3, 4]]
      #|FROM
      #|  test;
    ),
  )
}

///|
test "PostgreSQL mixed bracket and ARRAY syntax" {
  let tokens = "SELECT ARRAY[[1, 2], [3, 4]] FROM test;"
  let stmt = parse_sql(dialect=Postgres::{  }, tokens).stmts[0] |> pretty_print
  inspect(
    stmt,
    content=(
      #|SELECT
      #|  ARRAY[[1, 2], [3, 4]]
      #|FROM
      #|  test;
    ),
  )
}

///|
// Negative tests: PostgreSQL-specific syntax should fail with other dialects

test "ARRAY syntax fails with MySQL dialect" {
  let tokens = "SELECT ARRAY[1, 2, 3] FROM test;"
  try {
    let _ = parse_sql(dialect=MySQL::{  }, tokens)
    abort("Expected parsing to fail with MySQL dialect")
  } catch {
    _e => () // Expected behavior - parsing should fail
  }
}

///|
test "Bracket array syntax fails with MySQL dialect" {
  let tokens = "SELECT [1, 2, 3] FROM test;"
  try {
    let _ = parse_sql(dialect=MySQL::{  }, tokens)
    abort("Expected parsing to fail with MySQL dialect")
  } catch {
    _e => () // Expected behavior - parsing should fail
  }
}

///|
test "ARRAY syntax fails with SQLite dialect" {
  let tokens = "SELECT ARRAY[1, 2, 3] FROM test;"
  try {
    let _ = parse_sql(dialect=SQLite::{  }, tokens)
    abort("Expected parsing to fail with SQLite dialect")
  } catch {
    _e => () // Expected behavior - parsing should fail
  }
}

///|
test "Bracket array syntax fails with SQLite dialect" {
  let tokens = "SELECT [1, 2, 3] FROM test;"
  try {
    let _ = parse_sql(dialect=SQLite::{  }, tokens)
    abort("Expected parsing to fail with SQLite dialect")
  } catch {
    _e => () // Expected behavior - parsing should fail
  }
}

///|
test "LISTEN statement fails with MySQL dialect" {
  let tokens = "LISTEN my_channel;"
  try {
    let _ = parse_sql(dialect=MySQL::{  }, tokens)
    abort("Expected parsing to fail with MySQL dialect")
  } catch {
    _e => () // Expected behavior - parsing should fail
  }
}

///|
test "NOTIFY statement fails with MySQL dialect" {
  let tokens = "NOTIFY my_channel;"
  try {
    let _ = parse_sql(dialect=MySQL::{  }, tokens)
    abort("Expected parsing to fail with MySQL dialect")
  } catch {
    _e => () // Expected behavior - parsing should fail
  }
}

///|
test "Complex PostgreSQL arrays fail with generic dialect" {
  let tokens = "SELECT ARRAY[ARRAY[1, 2], [3, 4]] FROM test;"
  try {
    let _ = parse_sql(dialect=Generic::{  }, tokens)
    abort("Expected parsing to fail with Generic dialect")
  } catch {
    _e => () // Expected behavior - parsing should fail
  }
}

///|
// PostgreSQL JSON operator tests

test "PostgreSQL JSON extract operator" {
  let tokens = "SELECT data -> 'key' FROM json_table;"
  let stmt = parse_sql(dialect=Postgres::{  }, tokens).stmts[0] |> pretty_print
  inspect(
    stmt,
    content=(
      #|SELECT
      #|  data -> 'key'
      #|FROM
      #|  json_table;
    ),
  )
}

///|
test "PostgreSQL JSON extract text operator" {
  let tokens = "SELECT data ->> 'key' FROM json_table;"
  let stmt = parse_sql(dialect=Postgres::{  }, tokens).stmts[0] |> pretty_print
  inspect(
    stmt,
    content=(
      #|SELECT
      #|  data ->> 'key'
      #|FROM
      #|  json_table;
    ),
  )
}

///|
test "PostgreSQL JSON path extract operator" {
  let tokens = "SELECT data #> ARRAY['key', 'subkey'] FROM json_table;"
  let stmt = parse_sql(dialect=Postgres::{  }, tokens).stmts[0] |> pretty_print
  inspect(
    stmt,
    content=(
      #|SELECT
      #|  data #> ARRAY['key', 'subkey']
      #|FROM
      #|  json_table;
    ),
  )
}

///|
test "PostgreSQL JSON contains operator" {
  let tokens = "SELECT data @> '{\"key\":\"value\"}' FROM json_table;"
  let stmt = parse_sql(dialect=Postgres::{  }, tokens).stmts[0] |> pretty_print
  inspect(
    stmt,
    content=(
      #|SELECT
      #|  data @> '{"key":"value"}'
      #|FROM
      #|  json_table;
    ),
  )
}

///|
test "PostgreSQL JSON contained in operator" {
  let tokens = "SELECT '{\"a\":1}' <@ data FROM json_table;"
  let stmt = parse_sql(dialect=Postgres::{  }, tokens).stmts[0] |> pretty_print
  inspect(
    stmt,
    content=(
      #|SELECT
      #|  '{"a":1}' <@ data
      #|FROM
      #|  json_table;
    ),
  )
}

///|
// PostgreSQL FILTER aggregation tests

test "PostgreSQL COUNT with FILTER" {
  let tokens = "SELECT count(*) FILTER (WHERE active) FROM users;"
  let stmt = parse_sql(dialect=Postgres::{  }, tokens).stmts[0] |> pretty_print
  inspect(
    stmt,
    content=(
      #|SELECT
      #|  count(*) FILTER (WHERE active)
      #|FROM
      #|  users;
    ),
  )
}

///|
test "PostgreSQL COUNT without FILTER" {
  let tokens = "SELECT count(*) FROM users;"
  let stmt = parse_sql(dialect=Postgres::{  }, tokens).stmts[0] |> pretty_print
  inspect(
    stmt,
    content=(
      #|SELECT
      #|  count(*)
      #|FROM
      #|  users;
    ),
  )
}

///|
test "PostgreSQL SUM with FILTER" {
  let tokens = "SELECT sum(amount) FILTER (WHERE status = 'completed') FROM orders;"
  let stmt = parse_sql(dialect=Postgres::{  }, tokens).stmts[0] |> pretty_print
  inspect(
    stmt,
    content=(
      #|SELECT
      #|  sum(amount) FILTER (WHERE status = 'completed')
      #|FROM
      #|  orders;
    ),
  )
}

///|
test "PostgreSQL multiple aggregations with FILTER" {
  let tokens = "SELECT count(*) FILTER (WHERE active), avg(age) FILTER (WHERE age > 18) FROM users;"
  let stmt = parse_sql(dialect=Postgres::{  }, tokens).stmts[0] |> pretty_print
  inspect(
    stmt,
    content=(
      #|SELECT
      #|  count(*) FILTER (WHERE active),
      #|  avg(age) FILTER (WHERE age > 18)
      #|FROM
      #|  users;
    ),
  )
}