<?php declare(strict_types=1);
/**
 * @author Ryan Spaeth <rspaeth@spaethtech.com>
 * @copyright 2025 - Spaeth Technologies, Archous Networks
 */

namespace SpaethTech\UCRM\SDK\Controllers;

use DateTime;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use SpaethTech\UCRM\SDK\Security\Crypto;

class FallbackController extends BaseController
{
  public function handlePublicRoute(Request $request, Response $response, string $path): Response
  {
    try {
      $server = $this->plugin->getServer();
      $config = $this->plugin->getConfig();
      $ucrmDB = $server->getUcrmDB();

      if (!$ucrmDB) {
        throw new \Exception("Database connection failed");
      }

      $provisioner_url = rtrim(trim($config->get("provisioner_url") ?? ""), "/");
      $nat_url = rtrim(trim($config->get("nat_url") ?? ""), "/");

      if (empty($provisioner_url)) {
        throw new \Exception("Provisioner URL not configured");
      }

      $services = $ucrmDB->query(<<<SQL
                SELECT "service_id", "status", "superseded_by_service_id", "deleted_at", "active_from", "active_to"
                  FROM "service";
                SQL
      )->fetchAll();

      foreach ($services as &$service) {
        $stmt = $ucrmDB->prepare("SELECT attribute_id, value FROM service_attribute WHERE service_id = ?");
        $stmt->execute([$service['service_id']]);
        $service["attributes"] = $stmt->fetchAll();
      }
    } catch (\Exception $e) {
      return $this->handleError($response, "Database error: " . $e->getMessage());
    }

    $data = [
      "timestamp" => (new DateTime())->format("c"),
      "instance_id" => $server->getInstanceId(),
      "plugin" => [
        "id" => $this->plugin->getId(),
        "version" => $this->plugin->getVersion(),
        "name" => $this->plugin->getName(),
        "hostname" => $server->getHostname(),
        "ucrm_api_url" => $server->getPublicUcrmApiUrl(),
        "ucrm_api_key" => $server->getUcrmToken(),
        "plugin_url" => $this->plugin->getPublicUrl(),
      ],
    ];

    try {
      if ($path === "client/service") {
        $queryParams = $request->getQueryParams();
        if (!isset($queryParams["_serviceId"])) {
          throw new \Exception("Missing required parameter: _serviceId");
        }
        $serviceId = filter_var($queryParams["_serviceId"], FILTER_VALIDATE_INT);
        if ($serviceId === false) {
          throw new \Exception("Invalid service ID format");
        }
        $data["service_id"] = $serviceId;
      }

      $host = $server->getSetting("hostname");
      if (empty($host)) {
        throw new \Exception("Hostname not configured");
      }

      $auth = $this->plugin->getAuth();
      if (!$auth) {
        throw new \Exception("Authentication not available");
      }

      $cryptoPassword = $auth->getCryptoPassword();
      if (empty($cryptoPassword)) {
        throw new \Exception("Crypto password not configured");
      }

      $jsonData = json_encode($data);
      if ($jsonData === false) {
        throw new \Exception("Failed to encode data as JSON");
      }

      $encryptedData = Crypto::encrypt($jsonData, $cryptoPassword);
      if ($encryptedData === false) {
        throw new \Exception("Failed to encrypt data");
      }

      $signature = "host=$host&data=" . $encryptedData . "&" . http_build_query($_GET);

      return $this->twig->render($response, "public.html.twig", [
        "provisioner_url" => $provisioner_url,
        "nat_url" => $nat_url,
        "path" => $path,
        "signature" => $signature,
        "plugin_url" => $this->plugin->getPublicUrl(),
        "plugin" => $this->plugin,
      ]);
    } catch (\Exception $e) {
      return $this->handleError($response, "Processing error: " . $e->getMessage());
    }
  }

  private function handleError(Response $response, string $message): Response
  {
    $errorHtml = "<html><body><h1>Error</h1><p>" . htmlspecialchars($message) . "</p></body></html>";
    $response->getBody()->write($errorHtml);
    return $response
      ->withHeader("Content-Type", "text/html")
      ->withStatus(500);
  }
}