<?php

namespace App\Addons\Services;

use Exception;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;

/**
 * Addon Loader Service
 * Auto-detects and loads addons from /addons directory
 */
class AddonLoader
{
    /**
     * Addons directory path
     */
    private const ADDONS_DIR = 'addons';

    /**
     * Required manifest file
     */
    private const MANIFEST_FILE = 'addon.json';

    /**
     * Get all detected addons
     */
    public function getAllAddons(): array
    {
        $addons = [];
        $addonsPath = base_path(self::ADDONS_DIR);

        if (! is_dir($addonsPath)) {
            return $addons;
        }

        $directories = File::directories($addonsPath);

        foreach ($directories as $directory) {
            $addonSlug = basename($directory);
            $addon = $this->loadAddon($addonSlug);

            if ($addon) {
                $addons[$addonSlug] = $addon;
            }
        }

        return $addons;
    }

    /**
     * Load addon by slug
     */
    public function loadAddon(string $slug): ?array
    {
        $addonPath = base_path(self::ADDONS_DIR.'/'.$slug);
        $manifestPath = $addonPath.'/'.self::MANIFEST_FILE;

        if (! file_exists($manifestPath)) {
            return null;
        }

        try {
            $manifest = json_decode(file_get_contents($manifestPath), true);

            if (! $manifest || ! isset($manifest['slug'])) {
                Log::warning("Invalid addon manifest: {$slug}");

                return null;
            }

            // Validate required fields
            $required = ['slug', 'name', 'version', 'provider'];
            foreach ($required as $field) {
                if (! isset($manifest[$field])) {
                    Log::warning("Addon {$slug} missing required field: {$field}");

                    return null;
                }
            }

            // Add path information
            $manifest['path'] = $addonPath;
            $manifest['enabled'] = $this->isAddonEnabled($slug);

            return $manifest;
        } catch (Exception $e) {
            Log::error("Error loading addon {$slug}: ".$e->getMessage());

            return null;
        }
    }

    /**
     * Check if addon is enabled
     */
    public function isAddonEnabled(string $slug): bool
    {
        $enabledAddons = $this->getEnabledAddons();

        return in_array($slug, $enabledAddons);
    }

    /**
     * Get list of enabled addon slugs
     */
    public function getEnabledAddons(): array
    {
        $configFile = storage_path('app/addons.json');

        if (! file_exists($configFile)) {
            return [];
        }

        try {
            $config = json_decode(file_get_contents($configFile), true);

            return $config['enabled'] ?? [];
        } catch (Exception $e) {
            Log::error('Error reading addons config: '.$e->getMessage());

            return [];
        }
    }

    /**
     * Load addon service provider
     */
    public function loadServiceProvider(string $slug, array $manifest): ?string
    {
        $providerClass = $manifest['provider'] ?? null;

        if (! $providerClass) {
            return null;
        }

        // Check if class exists
        if (! class_exists($providerClass)) {
            Log::warning("Addon {$slug} provider class not found: {$providerClass}");

            return null;
        }

        return $providerClass;
    }

    /**
     * Get addon routes file path
     */
    public function getRoutesPath(string $slug): ?string
    {
        $routesPath = base_path(self::ADDONS_DIR.'/'.$slug.'/routes.php');

        if (file_exists($routesPath)) {
            return $routesPath;
        }

        // Try web.php
        $webRoutesPath = base_path(self::ADDONS_DIR.'/'.$slug.'/routes/web.php');
        if (file_exists($webRoutesPath)) {
            return $webRoutesPath;
        }

        return null;
    }

    /**
     * Validate addon structure
     */
    public function validateAddon(string $slug): array
    {
        $errors = [];
        $addonPath = base_path(self::ADDONS_DIR.'/'.$slug);

        // Check directory exists
        if (! is_dir($addonPath)) {
            $errors[] = 'Addon directory not found';

            return ['valid' => false, 'errors' => $errors];
        }

        // Check manifest exists
        $manifestPath = $addonPath.'/'.self::MANIFEST_FILE;
        if (! file_exists($manifestPath)) {
            $errors[] = 'Manifest file (addon.json) not found';
        } else {
            $manifest = json_decode(file_get_contents($manifestPath), true);
            if (! $manifest) {
                $errors[] = 'Invalid JSON in manifest file';
            } else {
                // Check required fields
                $required = ['slug', 'name', 'version', 'provider'];
                foreach ($required as $field) {
                    if (! isset($manifest[$field])) {
                        $errors[] = "Missing required field: {$field}";
                    }
                }

                // Check provider class exists
                if (isset($manifest['provider']) && ! class_exists($manifest['provider'])) {
                    $errors[] = "Provider class not found: {$manifest['provider']}";
                }
            }
        }

        return [
            'valid' => empty($errors),
            'errors' => $errors,
        ];
    }
}
