<?php
namespace Zab\ZabSite\DataProcessing;

use TYPO3\CMS\ContentBlocks\DataProcessing\ContentBlockDataDecorator;
use TYPO3\CMS\ContentBlocks\Definition\TableDefinitionCollection;
use TYPO3\CMS\Core\Domain\RecordFactory;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3\CMS\Frontend\ContentObject\DataProcessorInterface;

/**
 * Automatically transforms DatabaseQueryProcessor results into ContentBlockData objects.
 * Resolves all variables that contain records from ContentBlocks tables.
 *
 * Usage in TypoScript (universal - no config needed):
 *   dataProcessing {
 *     900 = Zab\ZabSite\DataProcessing\ContentBlockRecordsProcessor
 *   }
 *
 * Or target specific variables:
 *   dataProcessing {
 *     900 = Zab\ZabSite\DataProcessing\ContentBlockRecordsProcessor
 *     900 {
 *       variables = infoHubItems,infoHubCategories
 *     }
 *   }
 */
class ContentBlockRecordsProcessor implements DataProcessorInterface
{
    public function __construct(
        protected readonly RecordFactory $recordFactory,
        protected readonly ContentBlockDataDecorator $contentBlockDataDecorator,
        protected readonly TableDefinitionCollection $tableDefinitionCollection,
    ) {}

    public function process(
        ContentObjectRenderer $cObj,
        array $contentObjectConfiguration,
        array $processorConfiguration,
        array $processedData
    ): array {
        $request = $cObj->getRequest();
        $this->contentBlockDataDecorator->setRequest($request);

        // If specific variables are listed, only process those
        $targetVars = !empty($processorConfiguration['variables'])
            ? array_map('trim', explode(',', $processorConfiguration['variables']))
            : null;

        foreach ($processedData as $varName => $items) {
            if ($targetVars !== null && !in_array($varName, $targetVars, true)) {
                continue;
            }
            if (!is_array($items) || !array_is_list($items) || empty($items)) {
                continue;
            }

            // Detect the table from the first item's data
            $firstRow = $items[0]['data'] ?? $items[0] ?? [];
            if (!is_array($firstRow)) {
                continue;
            }
            $table = $this->detectTable($firstRow);
            if ($table === null) {
                continue;
            }

            foreach ($items as $key => $item) {
                $row = $item['data'] ?? $item;
                $resolvedRecord = $this->recordFactory->createResolvedRecordFromDatabaseRow($table, $row);
                $contentBlockData = $this->contentBlockDataDecorator->decorate($resolvedRecord);
                $processedData[$varName][$key] = $contentBlockData;
            }
        }

        return $processedData;
    }

    /**
     * Detect the ContentBlocks table from a raw DB row by checking known tables.
     */
    private function detectTable(array $row): ?string
    {
        foreach ($this->tableDefinitionCollection as $tableDefinition) {
            $tableName = $tableDefinition->table;
            // Skip tt_content and pages — those are handled by the standard ContentBlocksDataProcessor
            if (in_array($tableName, ['tt_content', 'pages'], true)) {
                continue;
            }
            // Check if the row has columns that match this table's TCA fields
            foreach ($tableDefinition->tcaFieldDefinitionCollection as $field) {
                $uniqueName = $field->uniqueIdentifier;
                if (isset($row[$uniqueName])) {
                    return $tableName;
                }
            }
        }
        return null;
    }
}
