<?php
if (!defined('ABSPATH')) exit;

class WizMig_CPanel {
  private $host; private $user; private $pass;
  private $cookieFile; private $token;
  private $logged_in = false;

  public function __construct($host, $user, $pass) {
    $this->host = trim($host);
    $this->user = $user;
    $this->pass = $pass;
    $upload_dir = wp_upload_dir();
    $work = trailingslashit($upload_dir['basedir']) . 'wizhosting-migrator';
    if (!wp_mkdir_p($work)) throw new Exception('Cannot create work dir: '.$work);
    $this->cookieFile = $work . '/cpanel_cookies.txt';
    $this->ensure_session(true);
  }

  private function ensure_session($force=false) {
    if ($this->token && !$force) return;
    if (file_exists($this->cookieFile)) @unlink($this->cookieFile);
    $url = "https://{$this->host}:2083/login/?login_only=1";
    $ch = curl_init($url);
    curl_setopt_array($ch, [
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_POST => true,
      CURLOPT_POSTFIELDS => http_build_query(['user'=>$this->user, 'pass'=>$this->pass, 'goto_uri'=>'/']),
      CURLOPT_HTTPHEADER => ['Accept: application/json'],
      CURLOPT_SSL_VERIFYPEER => true,
      CURLOPT_SSL_VERIFYHOST => 2,
      CURLOPT_FOLLOWLOCATION => true,
      CURLOPT_COOKIEJAR => $this->cookieFile,
      CURLOPT_COOKIEFILE => $this->cookieFile,
      CURLOPT_TIMEOUT => 0,
    ]);
    $resp = curl_exec($ch);
    if ($resp === false) { $err = curl_error($ch); curl_close($ch); throw new Exception('cURL login error: '.$err); }
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    $json = json_decode($resp, true);
    if (!$json || empty($json['status'])) {
      throw new Exception('Login failed (HTTP '.$code.').');
    }
    if (empty($json['security_token'])) throw new Exception('Login failed: no security_token');
    $this->token = $json['security_token'];
    $this->logged_in = true;
  }

  private function decode_or_relogin($resp, $code, $path, $postFields, $headers, $retried) {
    $json = json_decode($resp, true);
    if (is_array($json)) return $json;
    if (stripos($resp, '<!DOCTYPE') !== false || stripos($resp, '<html') !== false || $code==401) {
      if (!$retried) {
        $this->ensure_session(true);
        return $this->call($path, $postFields, $headers, true);
      }
      throw new Exception('Invalid session or authentication required (HTML response from cPanel).');
    }
    throw new Exception('Invalid JSON from cPanel (HTTP '.$code.').');
  }

  private function call($path, $postFields = null, $headers = [], $retried=false) {
    $this->ensure_session(false);
    $url = "https://{$this->host}:2083{$this->token}{$path}";
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array_merge(['Accept: application/json'], $headers));
    curl_setopt($ch, CURLOPT_COOKIEJAR, $this->cookieFile);
    curl_setopt($ch, CURLOPT_COOKIEFILE, $this->cookieFile);
    if ($postFields !== null) { curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields); }
    $resp = curl_exec($ch);
    if ($resp === false) { $err = curl_error($ch); curl_close($ch); throw new Exception('cURL error: '.$err); }
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    $json = $this->decode_or_relogin($resp, $code, $path, $postFields, $headers, $retried);
    return isset($json['result']) ? $json['result'] : $json;
  }

  public function uapi($module, $func, $params = []) {
    return $this->call("/execute/{$module}/{$func}", http_build_query($params, '', '&'));
  }
  public function uapi_multipart($path, $fields = []) {
    return $this->call($path, $fields);
  }
  public function api2($module, $func, $params = []) {
    $base = [
      'cpanel_jsonapi_user'       => $this->user,
      'cpanel_jsonapi_apiversion' => 2,
      'cpanel_jsonapi_module'     => $module,
      'cpanel_jsonapi_func'       => $func,
    ];
    $qs = http_build_query(array_merge($base, $params), '', '&');
    return $this->call("/json-api/cpanel?{$qs}", null);
  }
}
