<?php

namespace FleekDash\Integrations\Core;

defined('ABSPATH') || exit;

/**
 * Integration Generator
 *
 * Generates boilerplate code for new integrations
 */
class IntegrationGenerator
{
    private string $integrationsPath;
    private string $templatesPath;
    private string $integrationsPathReal;

    public function __construct()
    {
        $this->integrationsPath = FLEEKDASH_PLUGIN_DIR . 'integrations';
        $this->templatesPath = FLEEKDASH_PLUGIN_DIR . 'integrations/Core/templates';
        $this->integrationsPathReal = \realpath($this->integrationsPath) ?: $this->integrationsPath;
    }

    /**
     * Resolve and validate that a path is within the integrations base directory.
     * Prevents path injection attacks (phpsecurity:S2083).
     *
     * @param string $relativePath Path segment (e.g. integration id or subpath)
     */
    private function resolvePathWithinBase(string $relativePath): string
    {
        // basename() strips any path traversal - ensures we only get the final segment
        $safeSegment = \basename($relativePath);
        if ($safeSegment !== $relativePath) {
            throw new IntegrationGeneratorException('Invalid path: path traversal not allowed');
        }
        $parentPath = \realpath($this->integrationsPathReal);
        if ($parentPath === false) {
            throw new IntegrationGeneratorException('Invalid integrations base path');
        }
        $resolvedFull = $parentPath . \DIRECTORY_SEPARATOR . $safeSegment;
        if (\strpos($resolvedFull, $parentPath) !== 0) {
            throw new IntegrationGeneratorException('Path traversal detected');
        }
        return $resolvedFull;
    }

    /**
     * Validate that a string is safe for use as a filename/class name (alphanumeric only).
     */
    private function validateSafeIdentifier(string $value): string
    {
        if (!\preg_match('/^[A-Za-z][A-Za-z0-9]*$/', $value)) {
            throw new IntegrationGeneratorException('Invalid identifier format');
        }
        return $value;
    }

    /**
     * Generate a new integration
     */
    public function generate(array $params): bool
    {
        $id = \sanitize_key($params['id']);
        $name = \sanitize_text_field($params['name']);
        $category = \sanitize_text_field($params['category'] ?? 'plugin');

        // Validate id to prevent path traversal (only alphanumeric, hyphen, underscore)
        if (empty($id) || !\preg_match('/^[a-z0-9_-]+$/', $id)) {
            throw new IntegrationGeneratorException('Invalid integration ID format');
        }

        // Ensure id produces valid PHP class name (must start with letter)
        $className = $this->getClassName($id);
        if (!\preg_match('/^[A-Za-z]/', $className)) {
            throw new IntegrationGeneratorException('Integration ID must start with a letter');
        }

        $integrationPath = $this->resolvePathWithinBase($id);

        // Check if already exists
        if (is_dir($integrationPath)) {
            throw new IntegrationGeneratorException("Integration '{$id}' already exists");
        }

        // Create directory structure
        $this->createDirectories($integrationPath);

        // Generate files
        $this->generateConfig($integrationPath, $params);
        $this->generateServiceProvider($integrationPath, $params);
        $this->generateIntegration($integrationPath, $params);
        $this->generateController($integrationPath, $params);

        return true;
    }

    /**
     * Create directory structure
     */
    private function createDirectories(string $path): void
    {
        $dirs = [
            $path,
            $path . '/Http/Controllers',
            $path . '/Services',
            $path . '/assets/js',
            $path . '/assets/css',
            $path . '/views'
        ];

        foreach ($dirs as $dir) {
            wp_mkdir_p($dir);
        }
    }

    /**
     * Generate config.json
     */
    private function generateConfig(string $path, array $params): void
    {
        $config = [
            'id' => $params['id'],
            'name' => $params['name'],
            'description' => $params['description'] ?? '',
            'version' => '1.0.0',
            'author' => $params['author'] ?? '',
            'category' => $params['category'] ?? 'plugin',
            'requires' => $params['requires'] ?? [],
            'settings' => []
        ];

        file_put_contents(
            $path . '/config.json',
            json_encode($config, JSON_PRETTY_PRINT),
        );
    }

    /**
     * Generate Service Provider
     */
    private function generateServiceProvider(string $path, array $params): void
    {
        $className = $this->validateSafeIdentifier($this->getClassName($params['id']));
        $template = $this->getServiceProviderTemplate();

        $content = \str_replace(
            ['{{className}}', '{{id}}', '{{namespace}}'],
            [$className, $params['id'], "FleekDash\\Integrations\\{$className}"],
            $template,
        );

        $filename = $className . 'ServiceProvider.php';
        \file_put_contents($path . \DIRECTORY_SEPARATOR . $filename, $content);
    }

    /**
     * Generate Integration class
     */
    private function generateIntegration(string $path, array $params): void
    {
        $className = $this->validateSafeIdentifier($this->getClassName($params['id']));
        $template = $this->getIntegrationTemplate();

        $content = \str_replace(
            ['{{className}}', '{{id}}', '{{namespace}}'],
            [$className, $params['id'], "FleekDash\\Integrations\\{$className}"],
            $template,
        );

        \file_put_contents($path . \DIRECTORY_SEPARATOR . 'Integration.php', $content);
    }

    /**
     * Generate API Controller
     */
    private function generateController(string $path, array $params): void
    {
        $className = $this->validateSafeIdentifier($this->getClassName($params['id']));
        $template = $this->getControllerTemplate();

        $content = str_replace(
            ['{{className}}', '{{id}}', '{{namespace}}'],
            [$className, $params['id'], "FleekDash\\Integrations\\{$className}\\Http\\Controllers"],
            $template,
        );

        $controllerPath = $path . \DIRECTORY_SEPARATOR . 'Http' . \DIRECTORY_SEPARATOR . 'Controllers';
        $filename = $className . 'Controller.php';
        \file_put_contents($controllerPath . \DIRECTORY_SEPARATOR . $filename, $content);
    }

    /**
     * Get class name from integration ID
     */
    private function getClassName(string $id): string
    {
        return str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $id)));
    }

    /**
     * Get service provider template
     */
    private function getServiceProviderTemplate(): string
    {
        return '<?php

namespace {{namespace}};

use FleekDash\Integrations\Core\ServiceProvider;

defined(\'ABSPATH\') || exit;

class {{className}}ServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->singleton({{className}}Service::class);
        $this->bind({{className}}Controller::class);
    }

    public function boot(): void
    {
        $this->registerAssets();
        $this->registerApiRoutes();
    }

    private function registerAssets(): void
    {
        // Register assets
    }

    private function registerApiRoutes(): void
    {
        // Register API routes
    }
}';
    }

    /**
     * Get integration template
     */
    private function getIntegrationTemplate(): string
    {
        return '<?php

namespace {{namespace}};

use FleekDash\Integrations\Core\Integration;

defined(\'ABSPATH\') || exit;

class {{className}}Integration extends Integration
{
    public function getServiceProvider(): string
    {
        return {{className}}ServiceProvider::class;
    }
}';
    }

    /**
     * Get controller template
     */
    private function getControllerTemplate(): string
    {
        return '<?php

namespace {{namespace}};

use WP_REST_Request;
use WP_REST_Response;

defined(\'ABSPATH\') || exit;

class {{className}}Controller
{
    public function index(WP_REST_Request $request): WP_REST_Response
    {
        return rest_ensure_response([
            \'message\' => \'{{className}} integration is working\'
        ]);
    }
}';
    }

    /**
     * List available templates
     */
    public function getAvailableTemplates(): array
    {
        return [
            'basic' => 'Basic integration with API endpoints',
            'plugin' => 'Plugin integration with WordPress hooks',
            'theme' => 'Theme integration with custom features',
            'api' => 'External API integration'
        ];
    }
}
