<?php

namespace Maestro\Core\DataTables\Resources;

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

/**
 * DataTable resource for projects. Table: projects.
 * Joins companies for company_name.
 *
 * Global list: rows limited to ScopedAccessService::getAllowedProjectIds (direct / inherited project scope).
 * When filters.company_id is present with op equals, rows are all projects for that company if the user may
 * access the company and has company.projects.view (same rules as CompanyProjectController).
 */
class ProjectsTable implements DataTableResource
{
    public function key(): string
    {
        return 'projects';
    }

    /**
     * Module access: allow if user has projects.view (resolver global or Spatie). Data is scoped in baseQuery (Phase 6.1.1).
     */
    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(), 'projects.view')) {
            throw new AuthorizationException('You do not have permission to view the projects list.');
        }

        $companyId = $this->resolvedCompanyIdFromFilters($request);
        if ($companyId !== null) {
            $scopedAccess = app(ScopedAccessService::class);
            if (! $scopedAccess->userCanAccessCompany($request->user(), $companyId)) {
                throw new AuthorizationException('You do not have access to this company.');
            }
            if (! $resolver->userHasPermission($request->user(), 'company', $companyId, 'company.projects.view')) {
                throw new AuthorizationException('You do not have access to projects in this company.');
            }
        }
    }

    public function baseQuery(Request $request): Builder
    {
        $companyId = $this->resolvedCompanyIdFromFilters($request);
        if ($companyId !== null) {
            return $this->projectsQueryWithCompanyJoin()
                ->where('projects.company_id', $companyId);
        }

        $scopedAccess = app(ScopedAccessService::class);
        $allowedIds = $scopedAccess->getAllowedProjectIds($request->user());
        if ($allowedIds === []) {
            return Project::query()->whereRaw('1 = 0');
        }

        return $this->projectsQueryWithCompanyJoin()
            ->whereIn('projects.id', $allowedIds);
    }

    private function projectsQueryWithCompanyJoin(): Builder
    {
        return Project::query()
            ->leftJoin('companies', 'projects.company_id', '=', 'companies.id')
            ->select('projects.*', 'companies.name as company_name');
    }

    /**
     * Company-scoped project list (e.g. /companies/{id}/projects) sends filters.company_id equals.
     */
    private function resolvedCompanyIdFromFilters(Request $request): ?int
    {
        $filters = $request->input('filters', []);
        $companyIdFilter = $filters['company_id'] ?? null;
        if (! is_array($companyIdFilter) || ! array_key_exists('value', $companyIdFilter)) {
            return null;
        }
        $value = $companyIdFilter['value'];
        if (! is_numeric($value) || (int) $value <= 0) {
            return null;
        }
        $op = $companyIdFilter['op'] ?? 'equals';
        if ($op !== 'equals') {
            return null;
        }

        return (int) $value;
    }

    public function columns(): array
    {
        return [
            [
                'key' => 'id',
                'expr' => 'projects.id',
                'type' => 'number',
                'sortable' => true,
                'searchable' => false,
                'filterable' => false,
                'filterMode' => 'equals',
                'label' => __('datatable.columns.projects.id'),
                'defaultVisible' => false,
            ],
            [
                'key' => 'company_id',
                'expr' => 'projects.company_id',
                'type' => 'number',
                'sortable' => true,
                'searchable' => false,
                'filterable' => true,
                'filterMode' => 'equals',
                'label' => __('datatable.columns.projects.company_id'),
                'defaultVisible' => false,
            ],
            [
                'key' => 'name',
                'expr' => 'projects.name',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.projects.name'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'relationship_type',
                'expr' => 'projects.relationship_type',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'equals',
                'label' => __('datatable.columns.projects.relationship_type'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'project_number',
                'expr' => 'projects.project_number',
                'type' => 'text',
                'sortable' => true,
                'sortExpressions' => [
                    "CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(projects.project_number, '-', 2), '-', -1) AS UNSIGNED)",
                    "CAST(SUBSTRING_INDEX(projects.project_number, '-', -1) AS UNSIGNED)",
                ],
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.projects.project_number'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'subsidy_number',
                'expr' => 'projects.subsidy_number',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.projects.subsidy_number'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'phase',
                'expr' => 'projects.phase',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'equals',
                'label' => __('datatable.columns.projects.phase'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'status',
                'expr' => 'projects.status',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'equals',
                'label' => __('datatable.columns.projects.status'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'company_name',
                'expr' => 'companies.name',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.projects.company_name'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'start_period',
                'expr' => 'projects.start_period',
                'type' => 'date',
                'sortable' => true,
                'searchable' => false,
                'filterable' => true,
                'filterMode' => 'date_equals',
                'label' => __('datatable.columns.projects.start_period'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'end_period',
                'expr' => 'projects.end_period',
                'type' => 'date',
                'sortable' => true,
                'searchable' => false,
                'filterable' => true,
                'filterMode' => 'date_equals',
                'label' => __('datatable.columns.projects.end_period'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'created_at',
                'expr' => 'projects.created_at',
                'type' => 'date',
                'sortable' => true,
                'searchable' => false,
                'filterable' => true,
                'filterMode' => 'date_equals',
                'label' => __('datatable.columns.projects.created_at'),
                'defaultVisible' => true,
            ],
        ];
    }

    /**
     * @param  object  $model  Project instance (with company_name from join)
     * @return array<string, mixed>
     */
    public function transformRow(object $model): array
    {
        $startPeriod = $model->start_period ?? null;
        $endPeriod = $model->end_period ?? null;
        $createdAt = $model->created_at ?? null;

        return [
            'id' => $model->id,
            'company_id' => $model->company_id ?? null,
            'name' => $model->name ?? '',
            'relationship_type' => $model->relationship_type ?? '',
            'project_number' => $model->project_number ?? '',
            'subsidy_number' => $model->subsidy_number ?? '',
            'phase' => $model->phase ?? '',
            'status' => $model->status ?? '',
            'company_name' => $model->company_name ?? '',
            'start_period' => $startPeriod instanceof \DateTimeInterface ? $startPeriod->format('Y-m-d') : (string) $startPeriod,
            'end_period' => $endPeriod instanceof \DateTimeInterface ? $endPeriod->format('Y-m-d') : (string) $endPeriod,
            'created_at' => $createdAt instanceof \DateTimeInterface ? $createdAt->format('Y-m-d H:i:s') : (string) $createdAt,
        ];
    }
}
