<?php

namespace App\Services\Api\Actions;

use App\Models\Environments\Environment;
use App\Models\Environments\Plugin;
use App\Services\Api\Actions\Concerns\LogsPluginFailures;
use Illuminate\Http\Request;

class PluginsAction implements ActionInterface
{
    use LogsPluginFailures;

    public function execute(Request $request, array $payload): array
    {
        /** @var Environment $environment */
        $environment = $request->input('_environment');
        $plugins = $payload['data']['plugins'] ?? [];

        $processed = 0;
        $errors = [];

        foreach ($plugins as $pluginData) {
            try {
                $this->processPlugin($environment, $pluginData);
                $processed++;
            } catch (\Throwable $e) {
                $errors[] = $this->registrarPluginFallido($environment, $pluginData, $e);
            }
        }

        return [
            'processed' => $processed,
            'total' => count($plugins),
            'errors' => $errors,
        ];
    }

    /**
     * Procesa un plugin individual (crear o actualizar)
     * 
     * @param Environment $environment
     * @param array $pluginData
     * @return void
     */
    private function processPlugin(Environment $environment, array $pluginData): void
    {
        $name = $pluginData['name'] ?? null;
        $component = $pluginData['component'] ?? null;

        if (!$name && !$component) {
            throw new \InvalidArgumentException('El plugin debe tener al menos name o component');
        }

        // Buscar plugin existente
        $plugin = Plugin::where('environment_id', $environment->id)
            ->where(function ($query) use ($name, $component) {
                if ($name) {
                    $query->where('name', $name);
                }
                if ($component) {
                    $query->orWhere('component', $component);
                }
            })
            ->first();

        // Preparar atributos del plugin
        // versionrequires es obligatorio (integer), usar 0 como valor por defecto si no viene
        $versionRequires = $pluginData['versionrequires'] ?? null;
        if ($versionRequires === null) {
            // Si no viene versionrequires, usar 0 como valor por defecto
            // En Moodle, versionrequires es un integer que representa la versión mínima requerida
            $versionRequires = 0;
        }

        // **`type`, `versiondisk` y `versiondb` son NOT NULL en la tabla**, así que un
        // `null` aquí no guardaba el plugin: reventaba la petición entera con
        // SQLSTATE 23000. Y no es un caso rebuscado — es justo el del plugin **ausente
        // del disco**, que Moodle tiene registrado en la base de datos y cuyos ficheros
        // no están: no hay `versiondisk` que enviar.
        //
        // Se guarda `'0'`, que es lo que ya usaba `SyncAction` para lo mismo y lo que
        // `desfase()` lee como «esta versión no la sabemos».
        $pluginAttributes = [
            'environment_id' => $environment->id,
            'name' => $name,
            'component' => $component,
            'type' => $pluginData['type'] ?? '',
            'versiondisk' => (string) ($pluginData['versiondisk'] ?? $pluginData['version'] ?? '0'),
            'versiondb' => (string) ($pluginData['versiondb'] ?? $pluginData['version'] ?? '0'),
            'versionrequires' => (int) $versionRequires, // Asegurar que sea integer
            'pluginsupported' => $pluginData['pluginsupported'] ?? null,
            'pluginincompatible' => $pluginData['pluginincompatible'] ?? null,
            'release' => $pluginData['release'] ?? null,
            'has_dependencies' => isset($pluginData['dependencies']) && !empty($pluginData['dependencies']),
            'dependencies' => $pluginData['dependencies'] ?? null,
            'has_updates' => isset($pluginData['availableupdates']) && !empty($pluginData['availableupdates']),
            'availableupdates' => $pluginData['availableupdates'] ?? null,
        ];

        if ($plugin) {
            $plugin->update($pluginAttributes);
        } else {
            Plugin::create($pluginAttributes);
        }
    }
}

