<?php

declare(strict_types=1);

namespace PpPhp\Modules\Licensing\Controllers;

use PpPhp\Core\Config;
use PpPhp\Core\Security;
use PpPhp\Core\Licensing\PlanRegistry;

/**
 * Owner console for defining Plans / packages (Standard, Pro, Premium, …) and the
 * capabilities each one grants. Owner-only, authority-only (stripped from client
 * bundles). A client never authors a plan; it only receives its own plan's granted
 * capabilities inside its signed lease.
 */
final class PlanController
{
    public function __construct(private Config $config) {}

    private function gate(): void
    {
        Security::RequireAuth();
        if (!Security::IsOwner()) {
            redirect('/projects');
        }
    }

    private function json(array $payload, int $status = 200): void
    {
        http_response_code($status);
        header('Content-Type: application/json');
        echo json_encode($payload);
        exit;
    }

    private function input(): array
    {
        $j = json_decode((string) file_get_contents('php://input'), true);
        return is_array($j) ? $j : $_POST;
    }

    private function checkCsrf(array $in): void
    {
        if (!Security::CSRF()->Check((string) ($in['_token'] ?? ''))) {
            $this->json(['success' => false, 'message' => 'Invalid security token. Reload and try again.'], 400);
        }
    }

    public function index(): string
    {
        $this->gate();

        $plans        = PlanRegistry::all();
        $capabilities = PlanRegistry::CAPABILITIES;
        $iconChoices  = PlanRegistry::ICON_CHOICES;
        $colorChoices = PlanRegistry::COLOR_CHOICES;
        $baseUrl      = $this->config->get('base_url');
        $assetsUrl    = $this->config->get('assets_url');
        $user         = Security::CurrentUserData();
        $token        = Security::CSRF()->Token();

        ob_start();
        require __DIR__ . '/../Views/plans.php';
        return (string) ob_get_clean();
    }

    /** Create or update a plan. */
    public function save(): void
    {
        $this->gate();
        $in = $this->input();
        $this->checkCsrf($in);

        $name = trim((string) ($in['name'] ?? ''));
        if ($name === '') $this->json(['success' => false, 'message' => 'A plan name is required.'], 400);

        // Only recognised capability keys are honoured.
        $caps = [];
        $sent = is_array($in['capabilities'] ?? null) ? $in['capabilities'] : [];
        foreach (array_keys(PlanRegistry::CAPABILITIES) as $key) {
            $caps[$key] = !empty($sent[$key]);
        }

        // Per-plan build allowances (hour/day/week/month). Blank = inherit the global
        // default; 0 = unlimited; N = cap. Normalised by PlanRegistry.
        $buildLimits = PlanRegistry::normalizeLimits(is_array($in['build_limits'] ?? null) ? $in['build_limits'] : []);

        $slug = PlanRegistry::save([
            'slug'         => (string) ($in['slug'] ?? ''),
            'name'         => $name,
            'description'  => (string) ($in['description'] ?? ''),
            'order'        => (int) ($in['order'] ?? 99),
            'icon'         => (string) ($in['icon'] ?? ''),
            'color'        => (string) ($in['color'] ?? ''),
            'capabilities' => $caps,
            'build_limits' => $buildLimits,
            // Max size of one Virtual Database on this plan, in MB. Blank = the
            // shipped tier default; 0 = unlimited; N = cap. Hard-enforced by SQLite.
            'max_db_mb'    => (($m = $in['max_db_mb'] ?? '') === '' || $m === null) ? null : max(0, (int) $m),
        ]);
        if ($slug === '') $this->json(['success' => false, 'message' => 'That plan name is not usable.'], 400);

        $this->json(['success' => true, 'slug' => $slug, 'message' => 'Plan saved. New licences can use it now; existing ones adopt any capability change on their next daily check-in.']);
    }

    public function delete(): void
    {
        $this->gate();
        $in = $this->input();
        $this->checkCsrf($in);
        $slug = (string) ($in['slug'] ?? '');
        if ($slug === '' || !PlanRegistry::delete($slug)) {
            $this->json(['success' => false, 'message' => 'Could not delete that plan (you must keep at least one).'], 400);
        }
        $this->json(['success' => true, 'message' => 'Plan deleted. Licences already on it keep their name until reissued.']);
    }

    public function reset(): void
    {
        $this->gate();
        $in = $this->input();
        $this->checkCsrf($in);
        PlanRegistry::resetDefaults();
        $this->json(['success' => true, 'message' => 'Plans reset to Standard, Pro and Premium.']);
    }
}
