<?php

declare(strict_types=1);

namespace Maestro\Core\DataTables\Resources;

use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Maestro\Core\DataTables\DataTableResource;
use Maestro\Core\Support\AuthUserResolver;

final class UsersDataTable implements DataTableResource
{
    public function key(): string
    {
        return 'users';
    }

    public function authorize(Request $request): void
    {
        if (! $request->user()?->can('users.view')) {
            throw new AuthorizationException('You do not have permission to view users.');
        }
    }

    public function baseQuery(Request $request): Builder
    {
        $class = AuthUserResolver::eloquentModelClass();

        return $class::query()
            ->select(['users.id', 'users.name', 'users.email', 'users.is_active', 'users.created_at', 'users.updated_at'])
            ->with(['roles:id,name']);
    }

    /**
     * @return array<int, array<string, mixed>>
     */
    public function columns(): array
    {
        return [
            [
                'key' => 'id',
                'expr' => 'users.id',
                'type' => 'number',
                'sortable' => true,
                'searchable' => false,
                'filterable' => false,
                'filterMode' => 'equals',
                'label' => __('maestro::datatable.columns.users.id'),
                'defaultVisible' => false,
            ],
            [
                'key' => 'name',
                'expr' => 'users.name',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('maestro::datatable.columns.users.name'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'email',
                'expr' => 'users.email',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('maestro::datatable.columns.users.email'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'roles_txt',
                'expr' => 'users.id',
                'type' => 'text',
                'sortable' => false,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'filterHandler' => function (Builder $q, string $op, mixed $value, array $def): void {
                    $term = trim((string) $value);
                    if ($term === '') {
                        return;
                    }
                    $like = '%'.mb_strtolower($term).'%';
                    $q->whereHas('roles', fn (Builder $rq) => $rq->whereRaw('LOWER(name) LIKE ?', [$like]));
                },
                'label' => __('maestro::datatable.columns.users.roles_txt'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'is_active',
                'expr' => 'users.is_active',
                'type' => 'boolean',
                'sortable' => true,
                'searchable' => false,
                'filterable' => true,
                'filterMode' => 'equals',
                'label' => __('maestro::datatable.columns.users.is_active'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'created_at',
                'expr' => 'users.created_at',
                'type' => 'date',
                'sortable' => true,
                'searchable' => false,
                'filterable' => true,
                'filterMode' => 'date_equals',
                'label' => __('maestro::datatable.columns.users.created_at'),
                'defaultVisible' => true,
            ],
        ];
    }

    public function expandGlobalSearch(Builder $q, string $term): void
    {
        $like = '%'.mb_strtolower($term).'%';
        $q->orWhereHas('roles', fn (Builder $rq) => $rq->whereRaw('LOWER(name) LIKE ?', [$like]));
    }

    public function transformRow(object $model): array
    {
        $roles = [];
        foreach ($model->roles ?? [] as $r) {
            if (isset($r->name)) {
                $roles[] = $r->name;
            }
        }

        $createdAt = $model->created_at ?? null;

        return [
            'id' => $model->id,
            'name' => $model->name ?? '',
            'email' => $model->email ?? '',
            'roles_txt' => implode(', ', $roles),
            'roles' => array_values(array_filter($roles)),
            'is_active' => (bool) ($model->is_active ?? true),
            'created_at' => $createdAt instanceof \DateTimeInterface ? $createdAt->format(\DateTimeInterface::ATOM) : (string) $createdAt,
        ];
    }
}
