<?php

/**
 * Rajvidya Astro API — thin PHP SDK (PHP 8, cURL).
 *
 * Usage example:
 *   require 'Rajvidya.php';
 *   use Rajvidya\RajvidyaClient;
 *   use Rajvidya\RajvidyaError;
 *
 *   $client = new RajvidyaClient('rv_prod_ABC_xyzxyzxyz');
 *
 *   // GET endpoint with parameters
 *   try {
 *     $kundli = $client->kundli('chart-123', 'en');
 *     echo "Credits charged: " . $kundli->creditsCharged . "\n";
 *     echo "Moon sign: " . $kundli->data['moon_sign'] . "\n";
 *   } catch (RajvidyaError $e) {
 *     echo "API error: " . $e->getMessage() . "\n";
 *   }
 *
 *   // POST endpoint
 *   $chart = $client->createChart([
 *     'name' => 'John Doe',
 *     'gender' => 'MALE',
 *     'date_of_birth' => '1990-05-15',
 *     'time_of_birth' => '14:30',
 *     'place_of_birth' => 'New York, USA',
 *     'latitude' => 40.7128,
 *     'longitude' => -74.0060,
 *   ]);
 *   echo "Created chart: " . $chart->data['id'] . "\n";
 */

namespace Rajvidya;

class RajvidyaError extends \Exception {
  public int $statusCode;
  public string $errorCode;

  public function __construct(int $statusCode, string $code, string $message) {
    $this->statusCode = $statusCode;
    $this->errorCode = $code;
    parent::__construct("{$code}: {$message}");
  }
}

class ApiResponse {
  public int $statusCode;
  public array $data;
  public array $headers;
  public ?string $creditsCharged;
  public ?string $creditsRemaining;
  public ?string $quotaResetAt;

  public function __construct(int $statusCode, array $data, array $headers) {
    $this->statusCode = $statusCode;
    $this->data = $data;
    $this->headers = $headers;
    $this->creditsCharged = $headers['x-credits-charged'] ?? null;
    $this->creditsRemaining = $headers['x-credits-remaining'] ?? null;
    $this->quotaResetAt = $headers['x-quota-reset-at'] ?? null;
  }
}

class RajvidyaClient {
  private string $apiKey;
  private string $baseUrl;

  public function __construct(string $apiKey, string $baseUrl = 'https://rajvidya.com') {
    $this->apiKey = $apiKey;
    $this->baseUrl = rtrim($baseUrl, '/');
  }

  private function request(string $method, string $path, ?array $params = null, ?array $jsonBody = null): ApiResponse {
    $url = "{$this->baseUrl}{$path}";

    if ($params) {
      $query = http_build_query(array_filter($params, fn($v) => $v !== null));
      if ($query) {
        $url = "{$url}?{$query}";
      }
    }

    $curl = curl_init($url);
    curl_setopt_array($curl, [
      CURLOPT_CUSTOMREQUEST => $method,
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_HTTPHEADER => [
        'X-API-Key: ' . $this->apiKey,
        'User-Agent: rajvidya-php-sdk/1.0',
      ],
      CURLOPT_HEADERFUNCTION => function($curl, $header) use (&$responseHeaders) {
        $len = strlen($header);
        $header = explode(':', $header, 2);
        if (count($header) < 2) return $len;
        $name = strtolower(trim($header[0]));
        $value = trim($header[1]);
        if ($name !== '') {
          $responseHeaders[$name] = $value;
        }
        return $len;
      },
    ]);

    $responseHeaders = [];

    if ($jsonBody) {
      curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($jsonBody));
      curl_setopt($curl, CURLOPT_HTTPHEADER, array_merge(
        curl_getinfo($curl, CURLINFO_EFFECTIVE_URL) ? [] : [],
        [
          'X-API-Key: ' . $this->apiKey,
          'User-Agent: rajvidya-php-sdk/1.0',
          'Content-Type: application/json',
        ]
      ));
    }

    $body = curl_exec($curl);
    $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    $curlError = curl_error($curl);
    curl_close($curl);

    if ($curlError) {
      throw new RajvidyaError(0, 'network_error', "Network error: {$curlError}");
    }

    $data = json_decode($body ?: '{}', true);
    if ($data === null) {
      throw new RajvidyaError($statusCode, 'parse_error', 'Failed to parse response');
    }

    if ($statusCode >= 400) {
      $errorObj = $data['error'] ?? [];
      $code = $errorObj['code'] ?? 'http_error';
      $message = $errorObj['message'] ?? "HTTP {$statusCode}";
      throw new RajvidyaError($statusCode, $code, $message);
    }

    return new ApiResponse($statusCode, $data, $responseHeaders);
  }

  public function createChart(array $data): ApiResponse {
    return $this->request('POST', '/api/v1/charts/', null, $data);
  }

  public function readChart(string $chartId): ApiResponse {
    return $this->request('GET', '/api/v1/charts/', ['chart_id' => $chartId]);
  }

  public function updateChart(string $chartId, array $updates): ApiResponse {
    return $this->request('POST', '/api/v1/charts/', null, array_merge($updates, ['chart_id' => $chartId]));
  }

  public function kundli(string $chartId, string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/kundli/', ['chart_id' => $chartId, 'lang' => $lang]);
  }

  public function dasha(string $chartId, string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/dasha/', ['chart_id' => $chartId, 'lang' => $lang]);
  }

  public function doshas(string $chartId, string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/doshas/', ['chart_id' => $chartId, 'lang' => $lang]);
  }

  public function rashifal(string $chartId, string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/rashifal/', ['chart_id' => $chartId, 'lang' => $lang]);
  }

  public function todayHoroscope(string $chartId, string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/today/', ['chart_id' => $chartId, 'lang' => $lang]);
  }

  public function liveSky(float $latitude, float $longitude, string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/live-sky/', ['latitude' => $latitude, 'longitude' => $longitude, 'lang' => $lang]);
  }

  public function gochar(string $chartId, string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/gochar/', ['chart_id' => $chartId, 'lang' => $lang]);
  }

  public function panchang(float $latitude, float $longitude, string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/panchang/', ['latitude' => $latitude, 'longitude' => $longitude, 'lang' => $lang]);
  }

  public function festivals(float $latitude, float $longitude, string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/festivals/', ['latitude' => $latitude, 'longitude' => $longitude, 'lang' => $lang]);
  }

  public function choghadiya(float $latitude, float $longitude, string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/choghadiya/', ['latitude' => $latitude, 'longitude' => $longitude, 'lang' => $lang]);
  }

  public function muhurtaMarriage(string $brideChartId, string $groomChartId, string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/muhurta/marriage/', [
      'bride_chart_id' => $brideChartId,
      'groom_chart_id' => $groomChartId,
      'lang' => $lang,
    ]);
  }

  public function compatibility(string $chart1Id, string $chart2Id, string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/compatibility/', [
      'chart1_id' => $chart1Id,
      'chart2_id' => $chart2Id,
      'lang' => $lang,
    ]);
  }

  public function matchingReport(string $brideChartId, string $groomChartId, string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/reports/matching/', [
      'bride_chart_id' => $brideChartId,
      'groom_chart_id' => $groomChartId,
      'lang' => $lang,
    ]);
  }

  public function numerologyDashboard(string $name, string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/numerology/dashboard/', ['name' => $name, 'lang' => $lang]);
  }

  public function numerologyPro(string $name, string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/numerology/pro/', ['name' => $name, 'lang' => $lang]);
  }

  public function babyNames(string $birthChartId, string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/baby-names/', ['birth_chart_id' => $birthChartId, 'lang' => $lang]);
  }

  public function biorhythm(string $birthDate, string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/biorhythm/', ['birth_date' => $birthDate, 'lang' => $lang]);
  }

  public function remediesPrescription(string $chartId, string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/remedies/prescription/', ['chart_id' => $chartId, 'lang' => $lang]);
  }

  public function vastuAnalyze(string $floorPlanBase64, string $buildingType, int $orientationDegrees, string $lang = 'en'): ApiResponse {
    return $this->request('POST', '/api/v1/vastu/analyze/', null, [
      'floor_plan_base64' => $floorPlanBase64,
      'building_type' => $buildingType,
      'orientation_degrees' => $orientationDegrees,
      'lang' => $lang,
    ]);
  }

  public function vastuSurroundings(float $latitude, float $longitude, string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/vastu/surroundings/', ['latitude' => $latitude, 'longitude' => $longitude, 'lang' => $lang]);
  }

  public function vastuCatalog(string $lang = 'en'): ApiResponse {
    return $this->request('GET', '/api/v1/vastu/catalog/', ['lang' => $lang]);
  }
}
