<?php

namespace Ignite\Core\Models\Grid;

use Ignite\Core\Entities\Filters\QueryPermissionFilters;
use Ignite\Core\Entities\User;
use Ignite\Core\Http\Forms\ProfileForm;
use Ignite\Core\Models\Grid\QueryTable;
use Ignite\Core\Traits\ReportFormConfiguration;
use Illuminate\Database\DatabaseManager;
use Illuminate\Database\Query\Builder;
use Yajra\DataTables\DataTables;

class ParticipantTable extends QueryTable
{
    use ReportFormConfiguration {
        ReportFormConfiguration::getColumns as getFormColumns;
    }

    /**
     * The columns that should always be displayed when using the ReportFormConfiguration trait.
     * @var array
     */
    protected array $alwaysDisplay = ['action', 'checkbox', 'user_id', 'last_login_at', 'created_at'];

    /**
     * The form to configure report columns when using ReportFormConfiguration trait.
     * @var string
     */
    protected string $form = ProfileForm::class;

    /**
     * @var ParticipantFormatter
     */
    protected ParticipantFormatter $formatter;

    /**
     * ParticipantTable constructor.
     *
     * @param DataTables $datatables
     * @param DatabaseManager $databaseManager
     * @param ParticipantFormatter $formatter
     * @param array $params
     */
    public function __construct(
        DataTables           $datatables,
        DatabaseManager      $databaseManager,
        ParticipantFormatter $formatter,
        array                $params = []
    ) {
        parent::__construct($datatables, $databaseManager, $params);

        $this->formatter = $formatter;
    }

    /**
     * @return array
     */
    protected function getColumns(): array
    {
        $columns = $this->getFormColumns();
        unset($columns['ssn']);
        unset($columns[config('services.recaptcha.field_name')]);

        return $columns;
    }

    /**
     * The columns to show.
     *
     * @return array
     */
    public function columns(): array
    {
        return [
            'action' => $this->actionsColumn(),
            'user_id' => [
                'title' => 'User ID',
                'name' => 'participant.user_id',
                'orderable' => true,
                'exportable' => true,
            ],
            'last_login_at' => [
                'title' => 'Last Login',
                'name' => 'user.last_login_at',
                'orderable' => true,
                'exportable' => true,
            ],
            'created_at' => [
                'title' => 'Enrollment Date',
                'name' => 'participant.created_at',
                'orderable' => true,
                'exportable' => true,
            ],
        ];
    }

    /**
     * The participants query.
     *
     * @return Builder
     */
    public function query(): Builder
    {
        $columns = collect($this->getColumns())
            ->keyBy('name')
            ->except('actions')
            ->keys()
            ->toArray();

        $query = $this->getConnection()
            ->table('core_participant as participant')
            ->select($columns)
            ->leftJoin('core_user as user', 'user.user_id', '=', 'participant.user_id')
            ->where('user.internal', User::TYPE_PARTICIPANT)
            ->where('user.status', $this->status)
            ->whereNull('deleted_at');

        return QueryPermissionFilters::for('core.user.participant.browse')
            ->apply($query, 'participant');
    }

    /**
     * Get a map of column keys => functions to format columns.
     *
     * @return array
     */
    protected function getColumnFormattingMap(): array
    {
        return [
            'action' => function ($model) { return $this->formatter->actions($model); },
            'last_login_at' => function ($model) { return $this->formatter->lastLoginAt($model); },
            'created_at' => function ($model) { return $this->formatter->enrolledAt($model); },
            'agree_confirm_1' => function ($model) { return $this->formatter->agreeConfirm1($model); },
            'agree_confirm_2' => function ($model) { return $this->formatter->agreeConfirm2($model); },
            'archived' => function ($model) { return $this->formatter->archived($model); },
            'internal' => function ($model) { return $this->formatter->internal($model); },
            'status' => function ($model) { return $this->formatter->status($model); },
        ];
    }

    /**
     * Get default builder parameters.
     *
     * @return array
     */
    protected function getBuilderParameters(): array
    {
        $params = func_get_args();

        return parent::getBuilderParameters(array_merge([
            'order' => [[2, 'desc']],
        ], ...$params));
    }
}
