<?php

namespace PloverCRM\Core;

/**
 * Abstract Module Class
 * 
 * Base implementation for all modules with common functionality
 * 
 * ## Registering API Endpoints
 * 
 * Modules can register their own REST API endpoints using endpoint classes.
 * 
 * ### Step 1: Create an Endpoint Class
 * 
 * Create endpoint classes in your module's Endpoints folder that extend AbstractEndpoint:
 * 
 * ```php
 * // app/Modules/MyModule/Endpoints/MyCustomEndpoint.php
 * namespace PloverCRM\Modules\MyModule\Endpoints;
 * 
 * use PloverCRM\Core\Api\AbstractEndpoint;
 * use WP_REST_Request;
 * use WP_REST_Response;
 * use WP_Error;
 * 
 * class MyCustomEndpoint extends AbstractEndpoint
 * {
 *     public function getRoute(): string 
 *     { 
 *         return '/my-module/action'; 
 *     }
 *     
 *     public function getMethod(): string 
 *     { 
 *         return 'POST'; 
 *     }
 *     
 *     public function handle(WP_REST_Request $request): WP_REST_Response|WP_Error
 *     {
 *         // Your endpoint logic here
 *         $data = $request->get_json_params();
 *         
 *         return new WP_REST_Response([
 *             'success' => true,
 *             'data' => $data
 *         ], 200);
 *     }
 *     
 *     // Optional: Override permission check
 *     public function permissionCheck(): bool
 *     {
 *         return current_user_can('manage_options');
 *     }
 * }
 * ```
 * 
 * ### Step 2: Register in Your Module
 * 
 * ```php
 * public function register(): void
 * {
 *     add_action('rest_api_init', [$this, 'registerEndpoints']);
 * }
 * 
 * public function registerEndpoints(): void
 * {
 *     // Register single endpoint
 *     $this->registerModuleEndpoint(new Endpoints\MyCustomEndpoint($this->container));
 *     
 *     // Or register multiple endpoints at once
 *     $this->registerModuleEndpoints([
 *         new Endpoints\MyCustomEndpoint($this->container),
 *         new Endpoints\AnotherEndpoint($this->container),
 *     ]);
 * }
 * ```
 * 
 * The endpoint will be available at: `/wp-json/plover-crm/my-module/action`
 */
abstract class AbstractModule implements ModuleInterface
{
    /**
     * @var Container
     */
    protected $container;

    /**
     * @var string Module identifier
     */
    protected $id;

    /**
     * @var array Module dependencies
     */
    protected $dependencies = [];

    /**
     * Constructor
     * 
     * @param Container $container
     */
    public function __construct(Container $container)
    {
        $this->container = $container;
    }

    /**
     * {@inheritdoc}
     */
    public function register(): void
    {
        // Override in child classes
    }

    /**
     * {@inheritdoc}
     */
    public function boot(): void
    {
        // Override in child classes
    }

    /**
     * {@inheritdoc}
     */
    public function isEnabled(): bool
    {
        // By default, modules are enabled
        // Override in child classes for conditional loading
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function getId(): string
    {
        return $this->id;
    }

    /**
     * {@inheritdoc}
     */
    public function getDependencies(): array
    {
        return $this->dependencies;
    }

    /**
     * Get the container instance
     * 
     * @return Container
     */
    protected function getContainer(): Container
    {
        return $this->container;
    }

    /**
     * Resolve a service from the container
     * 
     * @param string $id
     * @return mixed
     */
    protected function resolve(string $id)
    {
        return $this->container->get($id);
    }

    /**
     * {@inheritdoc}
     */
    public function getMetadata(): array
    {
        // Default metadata - modules can override this
        return [
            'name' => ucwords(str_replace('_', ' ', $this->id)),
            'description' => 'No description provided',
            'version' => '1.0.0',
            'author' => 'WebPlover',
            'required' => false,
        ];
    }

    /**
     * Register a module endpoint
     * 
     * Helper method to register endpoint classes in the module's namespace
     * 
     * @param \PloverCRM\Core\Api\AbstractEndpoint $endpoint
     * @param string|null $namespace Optional custom namespace (defaults to 'plover-crm')
     * @return void
     */
    protected function registerModuleEndpoint($endpoint, ?string $namespace = null): void
    {
        $namespace = $namespace ?? 'plover-crm/v1';
        $endpoint->register($namespace);
    }

    /**
     * Register multiple module endpoints at once
     * 
     * @param array $endpoints Array of AbstractEndpoint instances
     * @param string|null $namespace Optional custom namespace
     * @return void
     */
    protected function registerModuleEndpoints(array $endpoints, ?string $namespace = null): void
    {
        foreach ($endpoints as $endpoint) {
            $this->registerModuleEndpoint($endpoint, $namespace);
        }
    }
}
