use strict;
use warnings;

use FindBin;
use lib "$FindBin::Bin/../lib";
use Test::More;
use MT::Test::Env;

our $test_env;

BEGIN {
    $test_env = MT::Test::Env->new;
    $ENV{MT_CONFIG} = $test_env->config_file;
}

use MT::Test;
use MT::Test::DataAPI;

$test_env->prepare_fixture('db');

use MT::App::DataAPI;
my $app = MT::App::DataAPI->new;

my $user = MT->model('author')->load(1);
$user->email('melody@example.com');
$user->save;

$app->user($user);

# manage_content_types permission remove.
my $system_perm = MT::Permission->load({author_id => $user->id, blog_id => 0});
my $permissions = $system_perm->permissions();
$permissions =~ s/'manage_content_types',?//;
$system_perm->permissions($permissions);
$system_perm->save();

my $site_id = 1;

normal_tests_for_create_category_set();
irregular_tests_for_create_category_set();

my $category_set
    = MT->model('category_set')->load( { name => 'create-category-set', } );
ok($category_set);

irregular_tests_for_get_category_set();
normal_tests_for_get_category_set();

irregular_tests_for_update_category_set();
normal_tests_for_update_category_set();

irregular_tests_for_list_category_sets();
normal_tests_for_list_category_sets();

irregular_tests_for_delete_category_sets();
normal_tests_for_delete_category_sets();

sub irregular_tests_for_create_category_set {
    test_data_api(
        {   note      => 'not logged in',
            path      => "/v4/sites/$site_id/categorySets",
            method    => 'POST',
            author_id => 0,
            params => { category_set => { name => 'create-category-set', }, },
            code   => 401,
        }
    );
    test_data_api(
        {   note   => 'invalid site',
            path   => '/v4/sites/1000/categorySets',
            method => 'POST',
            params => { category_set => { name => 'create-category-set', }, },
            code   => 404,
        }
    );
    test_data_api(
        {   note   => 'no resource',
            path   => "/v4/sites/$site_id/categorySets",
            method => 'POST',
            code   => 400,
        }
    );
    test_data_api(
        {   note   => 'no name',
            path   => "/v4/sites/$site_id/categorySets",
            method => 'POST',
            params => { category_set => {}, },
            code   => 409,
        }
    );
    test_data_api(
        {   note   => 'duplicated name',
            path   => "/v4/sites/$site_id/categorySets",
            method => 'POST',
            params => { category_set => { name => 'create-category-set', }, },
            code   => 409,
        }
    );
    test_data_api(
        {   note   => 'no permission',
            path   => "/v4/sites/$site_id/categorySets",
            method => 'POST',
            params =>
                { category_set => { name => 'create-category-set-3', }, },
            restrictions => { $site_id => ['save_category_set'], },
            code         => 403,
        }
    );
}

sub normal_tests_for_create_category_set {
    test_data_api(
        {   note   => 'non superuser',
            path   => "/v4/sites/$site_id/categorySets",
            method => 'POST',
            params => { category_set => { name => 'create-category-set', }, },
            callbacks => [
                {   name =>
                        'MT::App::DataAPI::data_api_save_permission_filter.category_set',
                    count => 1,
                },
                {   name =>
                        'MT::App::DataAPI::data_api_save_filter.category_set',
                    count => 1,
                },
                {   name =>
                        'MT::App::DataAPI::data_api_pre_save.category_set',
                    count => 1,
                },
                {   name =>
                        'MT::App::DataAPI::data_api_post_save.category_set',
                    count => 1,
                },
            ],
            result => sub {
                MT->model('category_set')->load(
                    {   blog_id => $site_id,
                        name    => 'create-category-set',
                    }
                );
            },
        }
    );
    test_data_api(
        {   note         => 'superuser',
            path         => "/v4/sites/$site_id/categorySets",
            is_superuser => 1,
            method       => 'POST',
            params =>
                { category_set => { name => 'create-category-set-2', }, },
            callbacks => [
                {   name =>
                        'MT::App::DataAPI::data_api_save_permission_filter.category_set',
                    count => 0,
                },
                {   name =>
                        'MT::App::DataAPI::data_api_save_filter.category_set',
                    count => 1,
                },
                {   name =>
                        'MT::App::DataAPI::data_api_pre_save.category_set',
                    count => 1,
                },
                {   name =>
                        'MT::App::DataAPI::data_api_post_save.category_set',
                    count => 1,
                },
            ],
            result => sub {
                MT->model('category_set')->load(
                    {   blog_id => $site_id,
                        name    => 'create-category-set-2',
                    }
                );
            },
        }
    );
}

sub irregular_tests_for_get_category_set {
    test_data_api(
        {   note   => 'invalid category_set id',
            path   => "/v4/sites/$site_id/categorySets/1000",
            method => 'GET',
            code   => 404,
        }
    );
    test_data_api(
        {   note   => 'other site',
            path   => "/v4/sites/2/category_sets/" . $category_set->id,
            method => 'GET',
            code   => 404,
        }
    );
}

sub normal_tests_for_get_category_set {
    test_data_api(
        {   note => 'not logged in',
            path => "/v4/sites/$site_id/categorySets/" . $category_set->id,
            author_id => 0,
            method    => 'GET',
            callbacks => [
                {   name =>
                        'MT::App::DataAPI::data_api_view_permission_filter.category_set',
                    count => 1,
                },
            ],
            result => sub {
                MT::DataAPI::Resource->from_object(
                    $category_set,
                    [   qw( blog categories createdBy createdDate id modifiedBy modifiedDate name updatable )
                    ]
                );
            },
        }
    );
    test_data_api(
        {   note   => 'non superuser',
            path   => "/v4/sites/$site_id/categorySets/" . $category_set->id,
            method => 'GET',
            callbacks => [
                {   name =>
                        'MT::App::DataAPI::data_api_view_permission_filter.category_set',
                    count => 1,
                },
            ],
            result => $category_set,
        }
    );
    test_data_api(
        {   note => 'superuser',
            path => "/v4/sites/$site_id/categorySets/" . $category_set->id,
            is_superuser => 1,
            method       => 'GET',
            callbacks    => [
                {   name =>
                        'MT::App::DataAPI::data_api_view_permission_filter.category_set',
                    count => 0,
                },
            ],
            result => $category_set,
        }
    );
    test_data_api(
        {   note => 'contentTypeCount by superuser',
            path => "/v4/sites/$site_id/categorySets/" . $category_set->id,
            up_to        => 4,
            params       => { fields => 'content_type_count' },
            is_superuser => 1,
            method       => 'GET',
            complete     => sub {
                my ($data, $body) = @_;
                my $got = $app->current_format->{unserialize}->($body);
                is($got->{content_type_count}, 0, 'content_type_count');
            },
        }
    );
    test_data_api(
        {   note => 'contentTypeCount by superuser',
            path => "/v5/sites/$site_id/categorySets/" . $category_set->id,
            params       => { fields => 'contentTypeCount' },
            is_superuser => 1,
            method       => 'GET',
            complete     => sub {
                my ($data, $body) = @_;
                my $got = $app->current_format->{unserialize}->($body);
                is($got->{contentTypeCount}, 0, 'contentTypeCount');
            },
        }
    );
    test_data_api(
        {   note => 'contentTypeCount by superuser',
            path => "/v5/sites/$site_id/categorySets/" . $category_set->id,
            params       => { fields => 'content_type_count' },
            is_superuser => 1,
            method       => 'GET',
            complete     => sub {
                my ($data, $body) = @_;
                my $got = $app->current_format->{unserialize}->($body);
                is($got->{contentTypeCount}, 0, 'contentTypeCount');
            },
        }
    );
    test_data_api(
        {   note => 'contentTypeCount only',
            path => "/v5/sites/$site_id/categorySets/" . $category_set->id,
            is_superuser => 1,
            method       => 'GET',
            complete     => sub {
                my ($data, $body) = @_;
                my $got = $app->current_format->{unserialize}->($body);
                ok(exists $got->{contentTypeCount}, 'exists contentTypeCount');
                ok(!exists $got->{content_type_count}, 'not exists content_type_count');
            },
        }
    );
    test_data_api(
        {   note         => 'search',
            path         => "/v4/sites/$site_id/categorySets",
            method       => 'GET',
            params       => { search => 'create-category-set-2' },
            is_superuser => 1,
            result       => sub {
                my @rows = MT->model('category_set')->load(
                    {   blog_id => $site_id,
                        name    => 'create-category-set-2'
                    }
                );
                +{  totalResults => scalar @rows,
                    items => MT::DataAPI::Resource->from_object( \@rows ),
                };
            },
        }
    );
    test_data_api(
        {   note         => 'search multiple rows',
            path         => "/v4/sites/$site_id/categorySets",
            method       => 'GET',
            params       => { search => 'create-category-set' },
            is_superuser => 1,
            result       => sub {
                my @rows = MT->model('category_set')->load(
                    {   blog_id => $site_id,
                        name    => [
                            'create-category-set', 'create-category-set-2'
                        ],
                    }
                );
                +{  totalResults => scalar @rows,
                    items => MT::DataAPI::Resource->from_object( \@rows ),
                };
            },
        }
    );
    test_data_api(
        {   note         => 'search not found',
            path         => "/v4/sites/$site_id/categorySets",
            method       => 'GET',
            params       => { search => 'not-found' },
            is_superuser => 1,
            result       => sub {
                +{  totalResults => 0,
                    items        => [],
                };
            },
        }
    );
}

sub irregular_tests_for_update_category_set {
    test_data_api(
        {   note   => 'not logged in',
            path   => "/v4/sites/$site_id/categorySets/" . $category_set->id,
            method => 'PUT',
            author_id => 0,
            params => { category_set => { name => 'update-category-set', }, },
            code   => 401,
        }
    );
    test_data_api(
        {   note   => 'invalid site_id',
            path   => '/v4/sites/1000/categorySets/' . $category_set->id,
            method => 'PUT',
            params => { category_set => { name => 'update-category-set', }, },
            code   => 404,
        }
    );
    test_data_api(
        {   note   => 'other site',
            path   => '/v4/sites/2/categorySets/' . $category_set->id,
            method => 'PUT',
            params => { category_set => { name => 'update-category-set', }, },
            code   => 404,
        }
    );
    test_data_api(
        {   note   => 'empty name',
            path   => "/v4/sites/$site_id/categorySets/" . $category_set->id,
            method => 'PUT',
            params => { category_set => { name => '', }, },
            code   => 409,
        }
    );
    test_data_api(
        {   note   => 'duplicated name',
            path   => "/v4/sites/$site_id/categorySets/" . $category_set->id,
            method => 'PUT',
            params =>
                { category_set => { name => 'create-category-set-2', }, },
            code => 409,
        }
    );
    test_data_api(
        {   note   => 'no permission',
            path   => "/v4/sites/$site_id/categorySets/" . $category_set->id,
            method => 'PUT',
            restrictions => { $site_id => ['save_category_set'], },
            params => { category_set => { name => 'update-category-set', }, },
            code   => 403,
        }
    );
}

sub normal_tests_for_update_category_set {
    test_data_api(
        {   note   => 'no superuser',
            path   => "/v4/sites/$site_id/categorySets/" . $category_set->id,
            method => 'PUT',
            params => { category_set => { name => 'update-category-set', }, },
            callbacks => [
                {   name =>
                        'MT::App::DataAPI::data_api_save_permission_filter.category_set',
                    count => 1,
                },
                {   name =>
                        'MT::App::DataAPI::data_api_save_filter.category_set',
                    count => 1,
                },
                {   name =>
                        'MT::App::DataAPI::data_api_pre_save.category_set',
                    count => 1,
                },
                {   name =>
                        'MT::App::DataAPI::data_api_post_save.category_set',
                    count => 1,
                },
            ],
            result => sub {
                ok( !MT->model('category_set')
                        ->exist( { name => 'create-category-set' } ) );
                $category_set = MT->model('category_set')->load(
                    {   id   => $category_set->id,
                        name => 'update-category-set'
                    }
                );
            },
        }
    );
    test_data_api(
        {   note   => 'superuser',
            path   => "/v4/sites/$site_id/categorySets/" . $category_set->id,
            method => 'PUT',
            is_superuser => 1,
            params =>
                { category_set => { name => 'update-category-set-2', }, },
            callbacks => [
                {   name =>
                        'MT::App::DataAPI::data_api_save_permission_filter.category_set',
                    count => 0,
                },
                {   name =>
                        'MT::App::DataAPI::data_api_save_filter.category_set',
                    count => 1,
                },
                {   name =>
                        'MT::App::DataAPI::data_api_pre_save.category_set',
                    count => 1,
                },
                {   name =>
                        'MT::App::DataAPI::data_api_post_save.category_set',
                    count => 1,
                },
            ],
            result => sub {
                ok( !MT->model('category_set')
                        ->exist( { name => 'update-category-set' } ) );
                $category_set = MT->model('category_set')->load(
                    {   id   => $category_set->id,
                        name => 'update-category-set-2'
                    }
                );
            },
        }
    );
}

sub irregular_tests_for_list_category_sets {
    test_data_api(
        {   note   => 'invalid site_id',
            path   => '/v4/sites/1000/categorySets',
            method => 'GET',
            code   => 404,
        }
    );
    test_data_api(
        {   note   => 'system scope',
            path   => '/v4/sites/0/categorySets',
            method => 'GET',
            code   => 404,
        }
    );
}

sub normal_tests_for_list_category_sets {
    test_data_api(
        {   note      => 'not logged in',
            path      => "/v4/sites/$site_id/categorySets",
            up_to     => 4,
            method    => 'GET',
            author_id => 0,
            callbacks => [
                {   name  => 'data_api_pre_load_filtered_list.category_set',
                    count => 2,
                },
            ],
            result => sub {
                +{  totalResults => 2,
                    items        => MT::DataAPI::Resource->from_object(
                        [   MT->model('category_set')
                                ->load( { blog_id => $site_id } )
                        ],
                        [   qw( blog categories createdBy createdDate id modifiedBy modifiedDate name updatable )
                        ],
                    ),
                };
            },

        }
    );
    test_data_api(
        {   note      => 'non superuser',
            path      => "/v4/sites/$site_id/categorySets",
            up_to     => 4,
            method    => 'GET',
            callbacks => [
                {   name  => 'data_api_pre_load_filtered_list.category_set',
                    count => 2,
                },
            ],
            result => sub {
                +{  totalResults => 2,
                    items        => MT::DataAPI::Resource->from_object(
                        [   MT->model('category_set')
                                ->load( { blog_id => $site_id } )
                        ]
                    ),
                };
            },
        }
    );
    test_data_api(
        {   note         => 'superuser',
            path         => "/v4/sites/$site_id/categorySets",
            up_to        => 4,
            method       => 'GET',
            is_superuser => 1,
            callbacks    => [
                {   name  => 'data_api_pre_load_filtered_list.category_set',
                    count => 2,
                },
            ],
            result => sub {
                +{  totalResults => 2,
                    items        => MT::DataAPI::Resource->from_object(
                        [   MT->model('category_set')
                                ->load( { blog_id => $site_id } )
                        ]
                    ),
                };
            },
        }
    );
    test_data_api(
        {   note      => 'not logged in',
            path      => "/v5/sites/$site_id/categorySets",
            method    => 'GET',
            author_id => 0,
            callbacks => [
                {   name  => 'data_api_pre_load_filtered_list.category_set',
                    count => 2,
                },
            ],
            result => sub {
                +{  totalResults => 2,
                    items        => MT::DataAPI::Resource->from_object(
                        [   MT->model('category_set')
                                ->load( { blog_id => $site_id }, { sort => 'name', direction => 'ascend', } )
                        ],
                        [   qw( blog categories createdBy createdDate id modifiedBy modifiedDate name updatable )
                        ],
                    ),
                };
            },

        }
    );
    test_data_api(
        {   note      => 'non superuser',
            path      => "/v5/sites/$site_id/categorySets",
            method    => 'GET',
            callbacks => [
                {   name  => 'data_api_pre_load_filtered_list.category_set',
                    count => 2,
                },
            ],
            result => sub {
                +{  totalResults => 2,
                    items        => MT::DataAPI::Resource->from_object(
                        [   MT->model('category_set')
                                ->load( { blog_id => $site_id }, { sort => 'name', direction => 'ascend', } )
                        ]
                    ),
                };
            },
        }
    );
    test_data_api(
        {   note         => 'superuser',
            path         => "/v5/sites/$site_id/categorySets",
            method       => 'GET',
            is_superuser => 1,
            callbacks    => [
                {   name  => 'data_api_pre_load_filtered_list.category_set',
                    count => 2,
                },
            ],
            result => sub {
                +{  totalResults => 2,
                    items        => MT::DataAPI::Resource->from_object(
                        [   MT->model('category_set')
                                ->load( { blog_id => $site_id }, { sort => 'name', direction => 'ascend', } )
                        ]
                    ),
                };
            },
        }
    );
}

sub irregular_tests_for_delete_category_sets {
    test_data_api(
        {   note   => 'not logged in',
            path   => "/v4/sites/$site_id/categorySets/" . $category_set->id,
            method => 'DELETE',
            author_id => 0,
            code      => 401,
        }
    );
    test_data_api(
        {   note   => 'invalid site_id',
            path   => '/v4/sites/1000/categorySets/' . $category_set->id,
            method => 'DELETE',
            code   => 404,
        }
    );
    test_data_api(
        {   note   => 'invalid category_set_id',
            path   => "/v4/sites/$site_id/categorySets/1000",
            method => 'DELETE',
            code   => 404,
        }
    );
    test_data_api(
        {   note   => 'other site',
            path   => '/v4/sites/2/categorySets/' . $category_set->id,
            method => 'DELETE',
            code   => 404,
        }
    );
    test_data_api(
        {   note   => 'no permission',
            path   => "/v4/sites/$site_id/categorySets/" . $category_set->id,
            method => 'DELETE',
            restrictions => { $site_id => ['delete_category_set'], },
            code         => 403,
        }
    );
}

sub normal_tests_for_delete_category_sets {
    test_data_api(
        {   note   => 'non superuser',
            path   => "/v4/sites/$site_id/categorySets/" . $category_set->id,
            method => 'DELETE',
            callbacks => [
                {   name =>
                        'MT::App::DataAPI::data_api_delete_permission_filter.category_set',
                    count => 1,
                },
                {   name =>
                        'MT::App::DataAPI::data_api_post_delete.category_set',
                    count => 1,
                },
            ],
            result => sub {
                $category_set;
            },
            complete => sub {
                ok( !MT->model('category_set')->load( $category_set->id ) );
            },
        }
    );

    my $cs = MT->model('category_set')->load;
    ok($cs);

    test_data_api(
        {   note         => 'superuser',
            path         => "/v4/sites/$site_id/categorySets/" . $cs->id,
            method       => 'DELETE',
            is_superuser => 1,
            callbacks    => [
                {   name =>
                        'MT::App::DataAPI::data_api_delete_permission_filter.category_set',
                    count => 0,
                },
                {   name =>
                        'MT::App::DataAPI::data_api_post_delete.category_set',
                    count => 1,
                },
            ],
            result => sub {
                $cs;
            },
            complete => sub {
                ok( !MT->model('category_set')->exist );
            },
        }
    );
}

done_testing;

