use strict;
use warnings;
use Test::More;

use DBIO::PostgreSQL::Diff::Column;

my $tables = {
  'public.users' => { schema_name => 'public', table_name => 'users' },
};

# Add column
my @ops = DBIO::PostgreSQL::Diff::Column->diff(
  { 'public.users' => [
    { column_name => 'id', data_type => 'integer', not_null => 1 },
  ]},
  { 'public.users' => [
    { column_name => 'id', data_type => 'integer', not_null => 1 },
    { column_name => 'email', data_type => 'text', not_null => 0 },
  ]},
  $tables, $tables,
);

is(scalar @ops, 1, 'one column to add');
is($ops[0]->action, 'add', 'action is add');
is($ops[0]->column_name, 'email', 'column name');
like($ops[0]->as_sql, qr/ALTER TABLE public\.users ADD COLUMN email text/, 'add column DDL');

# Drop column
@ops = DBIO::PostgreSQL::Diff::Column->diff(
  { 'public.users' => [
    { column_name => 'id', data_type => 'integer', not_null => 1 },
    { column_name => 'old_col', data_type => 'text', not_null => 0 },
  ]},
  { 'public.users' => [
    { column_name => 'id', data_type => 'integer', not_null => 1 },
  ]},
  $tables, $tables,
);

is(scalar @ops, 1, 'one column to drop');
is($ops[0]->action, 'drop', 'action is drop');
like($ops[0]->as_sql, qr/DROP COLUMN old_col/, 'drop column DDL');

# Alter column type
@ops = DBIO::PostgreSQL::Diff::Column->diff(
  { 'public.users' => [
    { column_name => 'name', data_type => 'varchar(50)', not_null => 0 },
  ]},
  { 'public.users' => [
    { column_name => 'name', data_type => 'text', not_null => 0 },
  ]},
  $tables, $tables,
);

is(scalar @ops, 1, 'one column altered');
is($ops[0]->action, 'alter', 'action is alter');
like($ops[0]->as_sql, qr/ALTER COLUMN name TYPE text/, 'alter column DDL');

# Add column with identity (BY DEFAULT)
@ops = DBIO::PostgreSQL::Diff::Column->diff(
  { 'public.users' => [] },
  { 'public.users' => [
    { column_name => 'id', data_type => 'integer', not_null => 1, identity => 'd' },
  ]},
  $tables, $tables,
);
is(scalar @ops, 1, 'one identity column to add');
like($ops[0]->as_sql, qr/ADD COLUMN id integer NOT NULL GENERATED BY DEFAULT AS IDENTITY/,
  'add column with identity BY DEFAULT');

# Add column with identity ALWAYS — default_value must be ignored
@ops = DBIO::PostgreSQL::Diff::Column->diff(
  { 'public.users' => [] },
  { 'public.users' => [
    { column_name => 'id', data_type => 'bigint', not_null => 1,
      identity => 'a', default_value => 'should_be_ignored' },
  ]},
  $tables, $tables,
);
like($ops[0]->as_sql, qr/GENERATED ALWAYS AS IDENTITY/,
  'add column with identity ALWAYS');
unlike($ops[0]->as_sql, qr/should_be_ignored/,
  'default_value skipped when identity is set');

# Alter column: add identity to existing column
@ops = DBIO::PostgreSQL::Diff::Column->diff(
  { 'public.users' => [
    { column_name => 'id', data_type => 'integer', not_null => 1, identity => '' },
  ]},
  { 'public.users' => [
    { column_name => 'id', data_type => 'integer', not_null => 1, identity => 'd' },
  ]},
  $tables, $tables,
);
is($ops[0]->action, 'alter', 'identity transition triggers alter');
like($ops[0]->as_sql,
  qr/ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY/,
  'ADD GENERATED for new identity');

# Alter column: drop identity
@ops = DBIO::PostgreSQL::Diff::Column->diff(
  { 'public.users' => [
    { column_name => 'id', data_type => 'integer', not_null => 1, identity => 'd' },
  ]},
  { 'public.users' => [
    { column_name => 'id', data_type => 'integer', not_null => 1, identity => '' },
  ]},
  $tables, $tables,
);
like($ops[0]->as_sql, qr/ALTER COLUMN id DROP IDENTITY/,
  'DROP IDENTITY for removed identity');

# Alter column: switch BY DEFAULT → ALWAYS
@ops = DBIO::PostgreSQL::Diff::Column->diff(
  { 'public.users' => [
    { column_name => 'id', data_type => 'integer', not_null => 1, identity => 'd' },
  ]},
  { 'public.users' => [
    { column_name => 'id', data_type => 'integer', not_null => 1, identity => 'a' },
  ]},
  $tables, $tables,
);
like($ops[0]->as_sql, qr/ALTER COLUMN id SET GENERATED ALWAYS/,
  'SET GENERATED for identity kind switch');

done_testing;
