#!/usr/bin/env php
<?php
use EEPROM\EEPROMContext;
use EEPROM\Uploads\{UploadInfo,UploadsContext};
use EEPROM\Pools\PoolInfo;
use EEPROM\Pools\Rules\{
    EnsureVariantRule,EnsureVariantRuleThumb,RemoveStaleRule,ScanForumRule
};
use EEPROM\Storage\{StorageContext,StorageRecord};

require_once __DIR__ . '/../eeprom.php';

$cronPath = sys_get_temp_dir() . '/eeprom-cron-' . hash('sha256', __DIR__) . '.lock';
if(is_file($cronPath))
    die('EEPROM cron script is already running.' . PHP_EOL);

touch($cronPath);
try {
    $pools = [];
    $getPool = fn($ruleRaw) => array_key_exists($ruleRaw->poolId, $pools) ? $pools[$ruleRaw->poolId] : (
        $pools[$ruleRaw->poolId] = $eeprom->poolsCtx->pools->getPool($ruleRaw->poolId)
    );

    // Run cleanup adjacent tasks first
    $rules = $eeprom->poolsCtx->pools->getPoolRules(types: ['remove_stale', 'scan_forum']);
    foreach($rules as $ruleRaw) {
        $poolInfo = $getPool($ruleRaw);
        $rule = $eeprom->poolsCtx->rules->create($ruleRaw);

        if($rule instanceof RemoveStaleRule) {
            printf('Removing stale entries for pool #%d...%s', $poolInfo->id, PHP_EOL);
            $eeprom->uploadsCtx->uploads->deleteStaleUploads(
                $poolInfo,
                $rule->inactiveForSeconds,
                $rule->ignoreUploadIds
            );
        } elseif($rule instanceof ScanForumRule) {
            //var_dump('scan_forum', $rule);
            // necessary stuff for this doesn't exist yet so this can remain a no-op
        }
    }
    echo PHP_EOL;

    printf('Purging denylisted file records...%s', PHP_EOL);
    $records = $eeprom->storageCtx->records->getFiles(denied: true);
    foreach($records as $record) {
        printf('Deleting file #%d...%s', $record->id, PHP_EOL);
        $eeprom->storageCtx->deleteFile($record);
    }
    echo PHP_EOL;

    printf('Purging uploads without an original variant...%s', PHP_EOL);
    $records = $eeprom->uploadsCtx->uploads->getUploads(variant: '', variantExists: false);
    foreach($records as $record) {
        printf('Deleting upload #%d...%s', $record->id, PHP_EOL);
        $eeprom->uploadsCtx->uploads->deleteUpload($record);
    }
    echo PHP_EOL;

    printf('Purging orphaned file records...%s', PHP_EOL);
    $records = $eeprom->storageCtx->records->getFiles(orphaned: true);
    foreach($records as $record) {
        printf('Deleting file #%d...%s', $record->id, PHP_EOL);
        $eeprom->storageCtx->deleteFile($record);
    }
    echo PHP_EOL;

    // Now run the ones that make new things
    $rules = $eeprom->poolsCtx->pools->getPoolRules(types: ['ensure_variant']);
    foreach($rules as $ruleRaw) {
        $poolInfo = $getPool($ruleRaw);
        $rule = $eeprom->poolsCtx->rules->create($ruleRaw);

        if($rule instanceof EnsureVariantRule) {
            if(!$rule->onCron)
                continue;

            $createVariant = null; // ensure this wasn't previously assigned
            if($rule->params instanceof EnsureVariantRuleThumb) {
                $createVariant = function(
                    StorageContext $storageCtx,
                    UploadsContext $uploadsCtx,
                    PoolInfo $poolInfo,
                    EnsureVariantRule $rule,
                    EnsureVariantRuleThumb $ruleInfo,
                    StorageRecord $originalInfo,
                    UploadInfo $uploadInfo
                ) {
                    $uploadsCtx->uploads->createUploadVariant(
                        $uploadInfo,
                        $rule->variant,
                        $storageCtx->createThumbnailFromRule(
                            $originalInfo,
                            $ruleInfo
                        )
                    );
                };
            }

            if(!isset($createVariant) || !is_callable($createVariant)) {
                printf('!!! Could not create a constructor for "%s" variants for pool #%d !!! Skipping for now...%s', $rule->variant, $poolInfo->id, PHP_EOL);
                continue;
            }

            printf('Ensuring existence of "%s" variants for pool #%d...%s', $rule->variant, $poolInfo->id, PHP_EOL);

            $uploads = $eeprom->uploadsCtx->uploads->getUploads(
                poolInfo: $poolInfo,
                variant: $rule->variant,
                variantExists: false
            );

            $processed = 0;
            foreach($uploads as $uploadInfo)
                try {
                    $createVariant(
                        $eeprom->storageCtx,
                        $eeprom->uploadsCtx,
                        $poolInfo,
                        $rule,
                        $rule->params,
                        $eeprom->storageCtx->records->getFile(
                            $eeprom->uploadsCtx->uploads->getUploadVariant($uploadInfo, '')->fileId
                        ),
                        $uploadInfo
                    );
                } catch(Exception $ex) {
                    printf('Exception thrown while processing "%s" variant for upload #%d in pool #%d:%s', $rule->variant, $uploadInfo->id, $poolInfo->id, PHP_EOL);
                    printf('%s%s', $ex->getMessage(), PHP_EOL);
                } finally {
                    ++$processed;
                }

            printf('Processed %d records!%s%s', $processed, PHP_EOL, PHP_EOL);
        }
    }
    echo PHP_EOL;
} finally {
    unlink($cronPath);
}