<?php

namespace Maestro\Core\DataTables\Resources;

use Maestro\Core\DataTables\DataTableResource;
use App\Models\ProjectTask;
use App\Services\Access\PermissionResolver;
use App\Services\Access\ScopedAccessService;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;

class TasksTable implements DataTableResource
{
    public function key(): string
    {
        return 'tasks';
    }

    public function authorize(Request $request): void
    {
        if (! $request->user()) {
            throw new AuthorizationException('You are not authorized to access this DataTable resource.');
        }
        $resolver = app(PermissionResolver::class);
        if (! $resolver->userHasModuleAccess($request->user(), 'tasks.view')) {
            throw new AuthorizationException('You do not have permission to view tasks.');
        }
    }

    public function baseQuery(Request $request): Builder
    {
        $scopedAccess = app(ScopedAccessService::class);
        $allowedProjectIds = $scopedAccess->getAllowedProjectIds($request->user());
        $allowedCompanyIds = $scopedAccess->getAllowedCompanyIds($request->user());

        if ($allowedProjectIds === [] && $allowedCompanyIds === []) {
            return ProjectTask::query()->whereRaw('1 = 0');
        }

        return ProjectTask::query()
            ->leftJoin('companies', 'companies.id', '=', 'tasks.company_id')
            ->leftJoin('projects', 'projects.id', '=', 'tasks.project_id')
            ->leftJoin('users as assignees', 'assignees.id', '=', 'tasks.assigned_person')
            ->select([
                'tasks.id',
                'tasks.company_id',
                'tasks.project_id',
                'tasks.phase',
                'tasks.title',
                'tasks.description',
                'tasks.required',
                'tasks.show_on_timeline',
                'tasks.status',
                'tasks.deadline_date',
                'tasks.sort_order',
                'tasks.assigned_person',
                'tasks.created_at',
                'tasks.updated_at',
                'companies.name as company_name',
                'projects.name as project_name',
                'assignees.name as assigned_person_name',
            ])
            ->where(function (Builder $query) use ($allowedProjectIds, $allowedCompanyIds): void {
                if ($allowedProjectIds !== []) {
                    $query->whereIn('tasks.project_id', $allowedProjectIds);
                }

                if ($allowedCompanyIds !== []) {
                    $query->orWhere(function (Builder $sub) use ($allowedCompanyIds): void {
                        $sub->whereNull('tasks.project_id')
                            ->whereIn('tasks.company_id', $allowedCompanyIds);
                    });
                }
            });
    }

    public function columns(): array
    {
        return [
            [
                'key' => 'id',
                'expr' => 'tasks.id',
                'type' => 'number',
                'sortable' => true,
                'searchable' => false,
                'filterable' => false,
                'filterMode' => 'equals',
                'label' => __('datatable.columns.tasks.id'),
                'defaultVisible' => false,
            ],
            [
                'key' => 'title',
                'expr' => 'tasks.title',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.tasks.title'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'description',
                'expr' => 'tasks.description',
                'type' => 'text',
                'sortable' => false,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.tasks.description'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'status',
                'expr' => 'tasks.status',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'equals',
                'label' => __('datatable.columns.tasks.status'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'phase',
                'expr' => 'tasks.phase',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'equals',
                'label' => __('datatable.columns.tasks.phase'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'company_name',
                'expr' => 'companies.name',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.tasks.company_name'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'project_name',
                'expr' => 'projects.name',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.tasks.project_name'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'assigned_person_name',
                'expr' => 'assignees.name',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.tasks.assigned_person_name'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'deadline_date',
                'expr' => 'tasks.deadline_date',
                'type' => 'date',
                'sortable' => true,
                'searchable' => false,
                'filterable' => true,
                'filterMode' => 'date_equals',
                'label' => __('datatable.columns.tasks.deadline_date'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'required',
                'expr' => 'tasks.required',
                'type' => 'boolean',
                'sortable' => true,
                'searchable' => false,
                'filterable' => true,
                'filterMode' => 'equals',
                'label' => __('datatable.columns.tasks.required'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'show_on_timeline',
                'expr' => 'tasks.show_on_timeline',
                'type' => 'boolean',
                'sortable' => true,
                'searchable' => false,
                'filterable' => true,
                'filterMode' => 'equals',
                'label' => __('datatable.columns.tasks.show_on_timeline'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'sort_order',
                'expr' => 'tasks.sort_order',
                'type' => 'number',
                'sortable' => true,
                'searchable' => false,
                'filterable' => true,
                'filterMode' => 'equals',
                'label' => __('datatable.columns.tasks.sort_order'),
                'defaultVisible' => false,
            ],
            [
                'key' => 'created_at',
                'expr' => 'tasks.created_at',
                'type' => 'date',
                'sortable' => true,
                'searchable' => false,
                'filterable' => true,
                'filterMode' => 'date_equals',
                'label' => __('datatable.columns.tasks.created_at'),
                'defaultVisible' => false,
            ],
            [
                'key' => 'updated_at',
                'expr' => 'tasks.updated_at',
                'type' => 'date',
                'sortable' => true,
                'searchable' => false,
                'filterable' => true,
                'filterMode' => 'date_equals',
                'label' => __('datatable.columns.tasks.updated_at'),
                'defaultVisible' => false,
            ],
        ];
    }

    public function transformRow(object $model): array
    {
        $deadlineDate = $model->deadline_date ?? null;
        $createdAt = $model->created_at ?? null;
        $updatedAt = $model->updated_at ?? null;

        return [
            'id' => $model->id,
            'company_id' => $model->company_id ?? null,
            'project_id' => $model->project_id ?? null,
            'title' => $model->title ?? '',
            'description' => $model->description ?? '',
            'status' => $model->status ?? '',
            'phase' => $model->phase ?? '',
            'company_name' => $model->company_name ?? '',
            'project_name' => $model->project_name ?? '',
            'assigned_person_name' => $model->assigned_person_name ?? '',
            'deadline_date' => $deadlineDate instanceof \DateTimeInterface ? $deadlineDate->format('Y-m-d') : (string) $deadlineDate,
            'required' => (bool) $model->required,
            'show_on_timeline' => (bool) $model->show_on_timeline,
            'sort_order' => (int) ($model->sort_order ?? 0),
            'created_at' => $createdAt instanceof \DateTimeInterface ? $createdAt->format('Y-m-d H:i:s') : (string) $createdAt,
            'updated_at' => $updatedAt instanceof \DateTimeInterface ? $updatedAt->format('Y-m-d H:i:s') : (string) $updatedAt,
        ];
    }
}
