<?php

declare(strict_types=1);

namespace Builder\Core\Http\Controllers\Resource;

use Builder\Core\Foundation\Registry;
use Builder\Core\Foundation\Tables\Column;
use Builder\Core\Http\Controllers\Concerns\HasIndexQuery;
use Builder\Core\Http\Controllers\Concerns\HasResourceResolving;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Symfony\Component\HttpFoundation\StreamedResponse;

final class ResourceExportController
{
    use HasIndexQuery;
    use HasResourceResolving;

    public function __construct(private readonly Registry $registry) {}

    public function __invoke(Request $request, string $resource): StreamedResponse
    {
        $definition = $this->resolveOrFail($resource);
        $this->authorizeResource($request, $definition, 'index');

        $query = $this->buildIndexQuery($request, $definition);
        $columns = array_values(array_filter($definition->getColumns(), fn (Column $c): bool => ! $c->isHidden()));
        $filename = $definition->getSlug().'-'.now()->format('Y-m-d').'.csv';

        return response()->streamDownload(function () use ($query, $columns): void {
            /** @var resource $handle */
            $handle = fopen('php://output', 'w');

            fputcsv($handle, array_map(fn (Column $c): string => $c->getLabel(), $columns));

            $query->chunk(500, function (Collection $chunk) use ($handle, $columns): void {
                foreach ($chunk as $record) {
                    $data = $record->toArray();

                    foreach ($columns as $col) {
                        $fmt = $col->getFormat();

                        if ($fmt !== null && array_key_exists($col->getKey(), $data)) {
                            $data[$col->getKey()] = $fmt($data[$col->getKey()]);
                        }
                    }

                    fputcsv($handle, array_map(fn (Column $c): mixed => $data[$c->getKey()] ?? '', $columns));
                }
            });

            fclose($handle);
        }, $filename, ['Content-Type' => 'text/csv']);
    }
}
