<?php

namespace Maestro\Core\DataTables\Resources;

use Maestro\Core\DataTables\DataTableResource;
use App\Models\CompanyLocation;
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 for company locations (vestigingen). Scoped by filters.company_id.
 */
class CompanyLocationsTable implements DataTableResource
{
    public function key(): string
    {
        return 'company-locations';
    }

    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(), 'companies.view')) {
            throw new AuthorizationException('You do not have permission to view company locations.');
        }

        $filters = $request->input('filters', []);
        $companyIdFilter = $filters['company_id'] ?? null;
        if (is_array($companyIdFilter) && isset($companyIdFilter['value'])) {
            $companyId = $companyIdFilter['value'];
            if (is_numeric($companyId) && (int) $companyId > 0) {
                $scopedAccess = app(ScopedAccessService::class);
                if (! $scopedAccess->userCanAccessCompany($request->user(), (int) $companyId)) {
                    throw new AuthorizationException('You do not have access to this company.');
                }
                if (! $resolver->userHasPermission($request->user(), 'company', (int) $companyId, 'company.locations.view')) {
                    throw new AuthorizationException('You do not have access to locations in this company.');
                }
            }
        }
    }

    public function baseQuery(Request $request): Builder
    {
        $scopedAccess = app(ScopedAccessService::class);
        $allowedCompanyIds = $scopedAccess->getAllowedCompanyIds($request->user());
        if ($allowedCompanyIds === []) {
            return CompanyLocation::query()->whereRaw('1 = 0');
        }

        $filters = $request->input('filters', []);
        $companyIdFilter = $filters['company_id']['value'] ?? null;

        if ($companyIdFilter === null || ! is_numeric($companyIdFilter)) {
            return CompanyLocation::query()->whereRaw('1 = 0');
        }

        $companyId = (int) $companyIdFilter;
        if (! in_array($companyId, $allowedCompanyIds, true)) {
            return CompanyLocation::query()->whereRaw('1 = 0');
        }

        // No orderBy here: DataTableQueryApplier::applySort owns ORDER BY. A fixed "standaard first"
        // + name clause would sort *before* the user column and breaks Adrestype (`type`) sorting.
        return CompanyLocation::query()
            ->where('company_locations.company_id', $companyId)
            ->select(
                'company_locations.id',
                'company_locations.company_id',
                'company_locations.name',
                'company_locations.street',
                'company_locations.house_number',
                'company_locations.postal_code',
                'company_locations.city',
                'company_locations.country',
                'company_locations.type',
                'company_locations.list_order',
                'company_locations.created_at',
                'company_locations.updated_at'
            );
    }

    public function columns(): array
    {
        return [
            [
                'key' => 'id',
                'expr' => 'company_locations.id',
                'type' => 'number',
                'sortable' => true,
                'searchable' => false,
                'filterable' => false,
                'filterMode' => 'equals',
                'label' => __('datatable.columns.company-locations.id'),
                'defaultVisible' => false,
            ],
            [
                'key' => 'company_id',
                'expr' => 'company_locations.company_id',
                'type' => 'number',
                'sortable' => false,
                'searchable' => false,
                'filterable' => false,
                'filterMode' => 'equals',
                'label' => __('datatable.columns.company-locations.company_id'),
                'defaultVisible' => false,
            ],
            [
                'key' => 'name',
                'expr' => 'company_locations.name',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.company-locations.name'),
                'defaultVisible' => false,
            ],
            [
                'key' => 'street',
                'expr' => 'company_locations.street',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.company-locations.street'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'house_number',
                'expr' => 'company_locations.house_number',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.company-locations.house_number'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'postal_code',
                'expr' => 'company_locations.postal_code',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.company-locations.postal_code'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'city',
                'expr' => 'company_locations.city',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.company-locations.city'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'list_order',
                'expr' => 'company_locations.list_order',
                'type' => 'number',
                'sortable' => true,
                'searchable' => false,
                'filterable' => false,
                'filterMode' => 'equals',
                'label' => __('datatable.columns.company-locations.list_order'),
                'defaultVisible' => false,
            ],
            [
                'key' => 'country',
                'expr' => 'company_locations.country',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.company-locations.country'),
                'defaultVisible' => false,
            ],
            [
                'key' => 'address_type',
                'expr' => 'company_locations.type',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.company-locations.address_type'),
                'defaultVisible' => false,
            ],
            [
                'key' => 'created_at',
                'expr' => 'company_locations.created_at',
                'type' => 'date',
                'sortable' => true,
                'searchable' => false,
                'filterable' => true,
                'filterMode' => 'date_equals',
                'label' => __('datatable.columns.company-locations.created_at'),
                'defaultVisible' => false,
            ],
        ];
    }

    /**
     * @return array<string, mixed>
     */
    public function transformRow(object $model): array
    {
        $createdAt = $model->created_at ?? null;

        $type = $model->type ?? '';

        return [
            'id' => $model->id,
            'company_id' => $model->company_id,
            'name' => $model->name ?? '',
            'street' => $model->street ?? '',
            'house_number' => $model->house_number ?? '',
            'postal_code' => $model->postal_code ?? '',
            'city' => $model->city ?? '',
            'country' => $model->country ?? '',
            'address_type' => $type === CompanyLocation::TYPE_DEFAULT ? 'standaard' : (string) $type,
            'is_default' => $type === CompanyLocation::TYPE_DEFAULT,
            'created_at' => $createdAt instanceof \DateTimeInterface ? $createdAt->format('Y-m-d H:i:s') : (string) $createdAt,
        ];
    }
}
