<?php

namespace Maestro\Core\DataTables\Resources;

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

/**
 * DataTable resource for company contact persons. Table: contact_people.
 * Shows contact persons with company, job function and department names.
 */
class CompaniesContactPersonsTable implements DataTableResource
{
    public function key(): string
    {
        return 'companies-contact-persons';
    }

    /**
     * Module access: allow if user has companies.view (resolver global or Spatie). Data is scoped in baseQuery (Phase 6.1.1).
     * When filters.company_id has a single value (company-scoped view), also require company.contacts.view in that company.
     */
    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 contact persons.');
        }

        $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.contacts.view')) {
                    throw new AuthorizationException('You do not have access to contacts in this company.');
                }
            }
        }
    }

    /**
     * Base query: contact persons in companies the user can access, with company, job function and department names.
     *
     * Filters used here (not applied again by DataTableQueryApplier):
     * - company_id: focus company (required; no fallback to all allowed when missing).
     * - network_scope: 'own' = only focus company; 'structure' = all companies in same structure (intersected with allowed).
     * The company_id column is filterable => false so the applier does not add an extra WHERE company_id = X.
     */
    public function baseQuery(Request $request): Builder
    {
        $scopedAccess = app(ScopedAccessService::class);
        $structureService = app(CompanyStructureService::class);

        $allowedCompanyIds = $scopedAccess->getAllowedCompanyIds($request->user());
        if ($allowedCompanyIds === []) {
            return ContactPerson::query()->whereRaw('1 = 0');
        }

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

        // Require focus company: no fallback to all allowed companies when company_id is missing or invalid.
        $targetCompanyIds = [];
        if ($companyIdFilter !== null && is_numeric($companyIdFilter)) {
            $companyId = (int) $companyIdFilter;

            if ($networkScope === 'own') {
                $targetCompanyIds = array_values(array_intersect($allowedCompanyIds, [$companyId]));
            } elseif ($networkScope === 'structure') {
                $company = Company::query()->find($companyId);
                if (! $company) {
                    $targetCompanyIds = [];
                } else {
                    $structureIds = $structureService->getStructureCompanyIds($company);
                    $targetCompanyIds = array_values(array_intersect($allowedCompanyIds, $structureIds));
                }
            }
        }

        if ($targetCompanyIds === []) {
            return ContactPerson::query()->whereRaw('1 = 0');
        }

        return ContactPerson::query()
            ->whereIn('contact_people.company_id', $targetCompanyIds)
            ->leftJoin('companies', 'contact_people.company_id', '=', 'companies.id')
            ->leftJoin('job_functions', 'contact_people.job_function_id', '=', 'job_functions.id')
            ->leftJoin('departments', 'contact_people.department_id', '=', 'departments.id')
            ->select(
                'contact_people.id',
                'contact_people.company_id',
                'contact_people.user_id',
                'contact_people.first_name',
                'contact_people.last_name',
                'contact_people.phone',
                'contact_people.email',
                'contact_people.job_function_id',
                'contact_people.department_id',
                'contact_people.signing_authority',
                'contact_people.receive_invoice',
                'contact_people.opt_in_newsletter',
                'contact_people.created_at',
                'contact_people.updated_at',
                'companies.name as company_name',
                'job_functions.name as job_function_name',
                'departments.name as department_name'
            )
            ->orderBy('contact_people.last_name')
            ->orderBy('contact_people.first_name');
    }

    public function columns(): array
    {
        return [
            [
                'key' => 'id',
                'expr' => 'contact_people.id',
                'type' => 'number',
                'sortable' => true,
                'searchable' => false,
                'filterable' => false,
                'filterMode' => 'equals',
                'label' => __('datatable.columns.companies-contact-persons.id'),
                'defaultVisible' => false,
            ],
            [
                'key' => 'company_id',
                'expr' => 'contact_people.company_id',
                'type' => 'number',
                'sortable' => false,
                'searchable' => false,
                'filterable' => false,
                'filterMode' => 'equals',
                'label' => __('datatable.columns.companies-contact-persons.company_id'),
                'defaultVisible' => false,
            ],
            [
                'key' => 'company_name',
                'expr' => 'companies.name',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.companies-contact-persons.company_name'),
                'defaultVisible' => false,
            ],
            [
                'key' => 'first_name',
                'expr' => 'contact_people.first_name',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.companies-contact-persons.first_name'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'last_name',
                'expr' => 'contact_people.last_name',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.companies-contact-persons.last_name'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'email',
                'expr' => 'contact_people.email',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.companies-contact-persons.email'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'phone',
                'expr' => 'contact_people.phone',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.companies-contact-persons.phone'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'job_function_name',
                'expr' => 'job_functions.name',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.companies-contact-persons.job_function_name'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'department_name',
                'expr' => 'departments.name',
                'type' => 'text',
                'sortable' => true,
                'searchable' => true,
                'filterable' => true,
                'filterMode' => 'contains',
                'label' => __('datatable.columns.companies-contact-persons.department_name'),
                'defaultVisible' => true,
            ],
            [
                'key' => 'signing_authority',
                'expr' => 'contact_people.signing_authority',
                'type' => 'text',
                'sortable' => true,
                'searchable' => false,
                'filterable' => true,
                'filterMode' => 'equals',
                'label' => __('datatable.columns.companies-contact-persons.signing_authority'),
                'defaultVisible' => false,
            ],
            [
                'key' => 'receive_invoice',
                'expr' => 'contact_people.receive_invoice',
                'type' => 'boolean',
                'sortable' => true,
                'searchable' => false,
                'filterable' => true,
                'filterMode' => 'equals',
                'label' => __('datatable.columns.companies-contact-persons.receive_invoice'),
                'defaultVisible' => false,
            ],
            [
                'key' => 'opt_in_newsletter',
                'expr' => 'contact_people.opt_in_newsletter',
                'type' => 'boolean',
                'sortable' => true,
                'searchable' => false,
                'filterable' => true,
                'filterMode' => 'equals',
                'label' => __('datatable.columns.companies-contact-persons.opt_in_newsletter'),
                'defaultVisible' => false,
            ],
            [
                'key' => 'created_at',
                'expr' => 'contact_people.created_at',
                'type' => 'date',
                'sortable' => true,
                'searchable' => false,
                'filterable' => true,
                'filterMode' => 'date_equals',
                'label' => __('datatable.columns.companies-contact-persons.created_at'),
                'defaultVisible' => false,
            ],
        ];
    }

    /**
     * @param  object  $model  ContactPerson instance (with joined company_name, job_function_name, department_name)
     * @return array<string, mixed>
     */
    public function transformRow(object $model): array
    {
        $createdAt = $model->created_at ?? null;

        return [
            'id' => $model->id,
            'company_id' => $model->company_id,
            'user_id' => $model->user_id,
            'company_name' => $model->company_name ?? '',
            'first_name' => $model->first_name ?? '',
            'last_name' => $model->last_name ?? '',
            'email' => $model->email ?? '',
            'phone' => $model->phone ?? '',
            'job_function_id' => $model->job_function_id,
            'job_function_name' => $model->job_function_name ?? '',
            'department_id' => $model->department_id,
            'department_name' => $model->department_name ?? '',
            'signing_authority' => $model->signing_authority ?? null,
            'receive_invoice' => (bool) ($model->receive_invoice ?? false),
            'opt_in_newsletter' => (bool) ($model->opt_in_newsletter ?? false),
            'created_at' => $createdAt instanceof \DateTimeInterface ? $createdAt->format('Y-m-d H:i:s') : (string) $createdAt,
        ];
    }
}

