<?php
declare(strict_types=1);

require_once __DIR__ . '/../lib/wp_common.php';

class SocialService {
  private array $cfg;
  private const PROVIDERS = ['linkedin', 'facebook'];

  public function __construct(array $cfg) {
    $this->cfg = $cfg;
  }

  public function validProvider(string $provider): bool {
    return in_array(strtolower($provider), self::PROVIDERS, true);
  }

  private function tenantsDir(): string {
    return rtrim((string)($this->cfg['tenants_dir'] ?? '/home/mytown/blog.mytown.ink/tenants'), '/');
  }

  private function tenantDir(string $ref): string {
    return $this->tenantsDir() . '/' . $ref;
  }

  private function socialDir(string $ref): string {
    $dir = $this->tenantDir($ref) . '/data/social';
    if (!is_dir($dir)) {
      @mkdir($dir, 0750, true);
    }
    return $dir;
  }

  private function queueDir(string $ref): string {
    $dir = $this->tenantDir($ref) . '/queue';
    if (!is_dir($dir)) {
      @mkdir($dir, 0750, true);
    }
    return $dir;
  }

  private function providerPath(string $ref, string $provider): string {
    return $this->socialDir($ref) . '/' . strtolower($provider) . '.json';
  }

  private function queuePath(string $ref): string {
    return $this->queueDir($ref) . '/jobs.jsonl';
  }

  private function masterKey(): string {
    $key = load_wp_master_key($this->cfg);
    if ($key === '') {
      throw new RuntimeException('Missing WP master key');
    }
    return $key;
  }

  public function storeToken(string $ref, string $provider, array $payload): bool {
    $plaintext = json_encode($payload, JSON_UNESCAPED_SLASHES);
    if ($plaintext === false) {
      return false;
    }
    $blob = crypto_encrypt_aes256gcm($plaintext, $this->masterKey(), strtolower($provider) . '-token');
    $data = [
      'version' => 1,
      'created_at' => date('c'),
      'blob' => $blob,
    ];
    return file_put_contents($this->providerPath($ref, $provider), json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX) !== false;
  }

  public function loadToken(string $ref, string $provider): ?array {
    $path = $this->providerPath($ref, $provider);
    if (!is_file($path)) return null;
    $raw = file_get_contents($path);
    if ($raw === false) return null;
    $data = json_decode($raw, true);
    if (!is_array($data) || !isset($data['blob'])) return null;
    $blob = $data['blob'];
    if (!is_array($blob)) return null;
    try {
      $decrypted = (string)crypto_decrypt_aes256gcm($blob, $this->masterKey(), strtolower($provider) . '-token');
    } catch (Throwable) {
      return null;
    }
    $decoded = json_decode($decrypted, true);
    return is_array($decoded) ? $decoded : null;
  }

  public function hasToken(string $ref, string $provider): bool {
    return $this->loadToken($ref, $provider) !== null;
  }

  public function queueJob(string $ref, array $job): bool {
    $path = $this->queuePath($ref);
    $jobLine = json_encode(array_merge([
      'created_at' => date('c'),
      'status' => 'queued',
    ], $job), JSON_UNESCAPED_SLASHES);
    if ($jobLine === false) return false;
    return file_put_contents($path, $jobLine . "\n", FILE_APPEND | LOCK_EX) !== false;
  }

  public function lastJob(string $ref): ?array {
    $path = $this->queuePath($ref);
    if (!is_file($path)) return null;
    $lines = array_filter(array_map('trim', file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: []));
    if (empty($lines)) return null;
    $last = array_pop($lines);
    $decoded = json_decode($last, true);
    return is_array($decoded) ? $decoded : null;
  }

  public function connectedProviders(string $ref): array {
    $out = [];
    foreach (self::PROVIDERS as $provider) {
      $out[$provider] = $this->hasToken($ref, $provider);
    }
    return $out;
  }
}
