<?php

declare(strict_types=1);

require_once __DIR__ . '/Env.php';
require_once __DIR__ . '/Logger.php';

class WpPublisher
{
    private string $baseUrl;
    private string $wpUser;
    private string $wpPass;

    public function __construct()
    {
        $this->baseUrl = rtrim(Env::get('WP_BASE_URL', ''), '/');
        $username = Env::get('WP_USERNAME', '');
        $appPassword = preg_replace('/\s+/', '', Env::get('WP_APP_PASSWORD', '') ?? '');

        if ($this->baseUrl === '') {
            throw new RuntimeException('WP_BASE_URL is not configured');
        }

        if ($username === '' || $appPassword === '') {
            throw new RuntimeException('WP username or app password is missing');
        }

        $this->wpUser = $username;
        $this->wpPass = $appPassword;
    }

    public function uploadImage(string $filePath, string $filename, string $altText): array
    {
        if (!is_file($filePath)) {
            throw new RuntimeException('Image file not found: ' . $filePath);
        }

        $payload = [
            'file' => new CURLFile($filePath, 'image/png', basename($filename)),
            'title' => basename($filename),
            'alt_text' => $altText,
        ];

        return $this->requestMultipart('/wp-json/wp/v2/media', $payload);
    }

    public function createPost(array $data): array
    {
        return $this->requestJson('POST', '/wp-json/wp/v2/posts', json_encode($data, JSON_THROW_ON_ERROR));
    }

    private function requestJson(string $method, string $endpoint, string|array|null $body = null, array $extraHeaders = []): array
    {
        $url = $this->baseUrl . $endpoint;
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
        curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
        curl_setopt($ch, CURLOPT_USERPWD, $this->wpUser . ':' . $this->wpPass);
        Logger::log('info', sprintf('WordPress request %s using CURLOPT_USERPWD auth', $endpoint));
        $headers = $extraHeaders;
        if ($body !== null && !$this->headerExists($headers, 'Content-Type')) {
            $headers[] = 'Content-Type: application/json';
        }
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_TIMEOUT, 60);

        if ($body !== null) {
            curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
        }

        $response = curl_exec($ch);
        $error = curl_error($ch);
        $errno = curl_errno($ch);
        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($errno !== 0) {
            throw new RuntimeException(sprintf('WordPress request failed (%s): %s', $endpoint, $error));
        }

        if ($response === false) {
            throw new RuntimeException('WordPress request returned empty response');
        }

        $decoded = json_decode($response, true);
        if ($status >= 400) {
            $message = $decoded['message'] ?? $decoded['error'] ?? 'Unknown error';
            throw new RuntimeException(sprintf('WordPress API error (%d): %s', $status, $message));
        }

        if (!is_array($decoded)) {
            throw new RuntimeException('WordPress response decoding failed');
        }

        return $decoded;
    }

    private function requestMultipart(string $endpoint, array $payload): array
    {
        $url = $this->baseUrl . $endpoint;
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
        curl_setopt($ch, CURLOPT_USERPWD, $this->wpUser . ':' . $this->wpPass);
        Logger::log('info', sprintf('WordPress request %s using CURLOPT_USERPWD auth', $endpoint));
        curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
        curl_setopt($ch, CURLOPT_TIMEOUT, 60);

        $response = curl_exec($ch);
        $error = curl_error($ch);
        $errno = curl_errno($ch);
        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($errno !== 0) {
            throw new RuntimeException(sprintf('WordPress media upload failed: %s', $error));
        }

        if ($response === false) {
            throw new RuntimeException('WordPress media upload returned empty response');
        }

        $decoded = json_decode($response, true);
        if (!is_array($decoded)) {
            throw new RuntimeException('WordPress upload decoding failed');
        }

        if ($status >= 400) {
            $message = $decoded['message'] ?? $decoded['error'] ?? 'Unknown upload error';
            throw new RuntimeException(sprintf('WordPress media error (%d): %s', $status, $message));
        }

        return $decoded;
    }

    private function headerExists(array $headers, string $name): bool
    {
        foreach ($headers as $header) {
            if (stripos($header, $name . ':') === 0) {
                return true;
            }
        }

        return false;
    }
}
