package AccountManager::App::Step4;

use Mojo::Base qw(AccountManager::App::Controller);

use DateTime;
use Email::MIME;
use Email::Sender::Simple;
use English qw(-no_match_vars);
use Syntax::Keyword::Try;
use Template::Constants qw(:chomp);

use AccountManager::Account;
use AccountManager::Token;
use AccountManager::Tools;

sub run {
    my $self = shift;

    my $config = $self->app()->config();
    my $log    = $self->app()->log();

    $self->init_db();
    $self->init_l10n();
    $self->init_user();

    if ($config->{app}->{login_url}) {
        return if !$self->check_authentication();
    }

    my $entityid = $self->param('entityid');
    my $email    = $self->param('email');
    my $token    = $self->param('token');
    my $validity = $self->param('validity');
    my $profiles = $self->every_param('profiles');
    my $db       = $self->stash('db');
    my $l10n     = $self->stash('l10n');

    my $sp = $self->get_sp(entityid => $entityid);
    return if !$sp;

    return if !$self->check_token(token => $token, entityid => $entityid);

    ## create test accounts
    my @accounts;

    my $creation_date  = DateTime->now();
    my $token_expiration_date = DateTime->now()->add(
        hours => $config->{service}->{tokens_validity_period}
    );
    my $account_expiration_date = DateTime->now()->add(
        days => $validity
    );

    my $download_token = AccountManager::Token->new(
        db              => $db,
        email_address   => $email,
        entityid        => $entityid,
        creation_date   => $creation_date,
        expiration_date => $token_expiration_date,
        secret          => AccountManager::Tools::generate_secret(20)
    );

    try {
        $download_token->save();
    } catch {
        return $self->abort(
            log_message  => "Failed to save download authentication token",
            user_message => "internal"
        );
    }

    my $key = AccountManager::Tools::generate_secret(10);

    foreach my $profile (@$profiles) {
        my $password = AccountManager::Tools::generate_password(10);
        my $account = AccountManager::Account->new(
            db              => $db,
            profile         => $profile,
            entityid        => $entityid,
            scope           => $config->{idp}->{scope},
            password        => $password,
            password_crypt  => AccountManager::Tools::encrypt($password, $key),
            password_hash   => AccountManager::Tools::sha256_hash($password),
            token           => $download_token->secret(),
            creation_date   => $creation_date,
            expiration_date => $account_expiration_date,
        );
        next unless $account->save();
        push @accounts, $account;
    }

    return $self->abort(
        log_message  => "Failed to create test accounts for SP $entityid",
        user_message => "accounts_creation_failure"
    ) if !@accounts;

    ## Update simpleSAMLphp configuration to enable test accounts
    my $accounts = AccountManager::Account->get_accounts(db => $db);

    try {
        AccountManager::Tools::update_ssp_authsources(
            $self->app()->home()->child('templates'),
            $config->{setup}->{accounts_file},
            $accounts
        );
    } catch($error) {
        return $self->abort(
            log_message  => "Failed to create simpleSAMLphp configuration file: $error",
            user_message => "accounts_creation_failure"
        );
    }

    $log->info(sprintf("Token validated for entityid=%s", $entityid));

    $self->stash(accounts => \@accounts);
    $self->stash(idp      => { name => $config->{idp}->{name} });
    $self->stash(sp       => { entityid => $entityid, url => $sp->information_url() });
    $self->stash(email    => $email);
    $self->stash(days     => $validity);
    $self->stash(
        download_url => $self->url_for('step5')->query(
            entityid => $entityid,
            token    => $download_token->secret(),
            key      => $key
        )
    );

    $self->render(
        status   => 200,
        template => 'step4',
        format   => 'html'
    );
}

1;