<?php

declare(strict_types=1);

namespace Maestro\Core\Http\Controllers\Api\DataTables;

use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Maestro\Core\DataTables\DataTableQueryApplier;
use Maestro\Core\DataTables\DataTableRegistry;
use Maestro\Core\Http\Controllers\Controller;
use Maestro\Core\Http\Requests\DataTables\ExportDataTableRequest;
use Maestro\Core\Http\Requests\DataTables\FetchDataTableRequest;
use Maestro\Core\Jobs\ExportDataTableJob;
use Maestro\Core\Models\DataTableExport;

use function activity;

final class DataTableController extends Controller
{
    public function __construct(
        private readonly DataTableRegistry $registry,
        private readonly DataTableQueryApplier $applier,
    ) {}

    public function columns(Request $request, string $resourceKey): JsonResponse
    {
        $resource = $this->registry->resolve($resourceKey);
        $resource->authorize($request);

        $defs = $resource->columns();
        $out = [];
        foreach ($defs as $def) {
            $key = $def['key'] ?? null;
            if ($key === null) {
                continue;
            }
            $out[] = [
                'key' => $key,
                'header' => $def['label'] ?? $key,
                'type' => $def['type'] ?? 'text',
                'searchable' => (bool) ($def['searchable'] ?? false),
                'filterable' => (bool) ($def['filterable'] ?? false),
                'defaultVisible' => (bool) ($def['defaultVisible'] ?? true),
            ];
        }

        return response()->json($out);
    }

    public function fetch(FetchDataTableRequest $request, string $resourceKey): JsonResponse
    {
        $resource = $this->registry->resolve($resourceKey);
        $resource->authorize($request);

        $query = $resource->baseQuery($request);
        $columns = $resource->columns();
        $payload = $request->validated();

        $countQuery = clone $query;
        $base = $countQuery->getQuery();
        $base->groups = null;
        $model = $countQuery->getModel();
        $idCol = $model ? $model->getTable().'.id' : 'id';
        $totalAll = $countQuery->distinct($idCol)->count($idCol);

        $result = $this->applier->apply(
            $query,
            $columns,
            $payload,
            fn (object $model) => $resource->transformRow($model),
            $resource,
        );

        $result['meta']['resourceKey'] = $resource->key();
        $result['meta']['totalAll'] = $totalAll;

        return response()->json($result);
    }

    public function export(ExportDataTableRequest $request, string $resourceKey): JsonResponse
    {
        $resource = $this->registry->resolve($resourceKey);
        $resource->authorize($request);

        $resourceLabel = trans('maestro::datatable.resources.'.$resourceKey);
        if ($resourceLabel === 'maestro::datatable.resources.'.$resourceKey) {
            $resourceLabel = $resourceKey;
        }

        $payload = $request->validated();
        $columns = $resource->columns();
        $exportColumns = $this->applier->orderedExportColumns($columns, $payload);
        if ($exportColumns === []) {
            return response()->json(['message' => 'No valid columns to export.'], 422);
        }

        $export = DataTableExport::create([
            'user_id' => $request->user()->id,
            'resource_key' => $resourceKey,
            'payload' => $payload,
            'status' => DataTableExport::STATUS_PENDING,
        ]);

        ExportDataTableJob::dispatch($export->id)->onQueue('exports');

        activity('data_export')
            ->causedBy($request->user())
            ->event('export')
            ->withProperties([
                'resource_key' => $resourceKey,
                'export_id' => $export->id,
                'status' => DataTableExport::STATUS_PENDING,
            ])
            ->log('Data export to CSV started for: '.$resourceKey);

        return response()->json([
            'id' => $export->id,
            'status' => $export->status,
            'resourceKey' => $resourceKey,
            'resourceLabel' => $resourceLabel,
            'pollingIntervalHintMs' => 3000,
        ], 201);
    }
}
