<?php

namespace onespace\tools\activeApi\components\clients;

use onespace\tools\activeApi\components\clients\base\BaseOneSpaceClient;
use Yii;
use yii\helpers\ArrayHelper;
use yii\web\NotFoundHttpException;

class DataReportClient extends BaseOneSpaceClient {
    public function serverUrl(): string {
        return Yii::$app->params['serviceUrls']['dataReport'];
    }

    /**
     * Register the generation of a static report
     */
    public function registerStaticReportRequest(string $reportType, string $requestedBy, string $siteId, array $params): array {
        return self::goPost("api/v1/register", [
            'service' => 'central',
            'type' => 'static',
            'reportType' => $reportType,
            'requestedBy' => $requestedBy,
            'siteId' => $siteId,
            'params' => $params,
        ]);
    }

    /**
     * Register the generation of a generic report
     */
    public function registerGenericReportRequest(string $endpoint, string $requestedBy, string $siteId, array $params, array $columnOrder): array {
        return self::goPost("api/v1/register", [
            'endpoint' => $endpoint,
            'service' => 'central',
            'type' => 'generic',
            'requestedBy' => $requestedBy,
            'siteId' => $siteId,
            'params' => $params,
            'columnOrder' => $columnOrder,
        ]);
    }

    /**
     * View results data for a specified report. Build out pagination and sorting into the
     * request URI.
     */
    public function viewReport(string $id, array $get, array $fields = []): array {
        $uri = ['id' => $id];
        $fields = ArrayHelper::merge(['pageSize', 'page', 'sort'], $fields);

        foreach ($fields as $field) {
            if (isset($get[$field])) {
                $uri[$field] = $get[$field];
            }
        }

        $url = "api/v1/view?" . http_build_query($uri);
        $response = self::goGet($url);
        $success = ArrayHelper::getValue($response, "data.success", false);
        $data = ArrayHelper::getValue($response, "data.dataProvider");

        return [
            'success' => $success,
            'data' => $data,
        ];
    }

    /**
     * Get a status report of a specific report.
     */
    public function getReportStatus(string $id): array {
        $response = self::goGet("api/v1/view/status?id={$id}");
        $success = ArrayHelper::getValue($response, "data.success", false);
        $data = ArrayHelper::getValue($response, "data.data");

        return [
            'success' => $success,
            'data' => $data,
        ];
    }

    /**
     * Perform a download passthrough from the data microservice
     *
     * @param   string  $id ULID id of the data report
     * @param   string  $type Type of available file types. For .pdfs set 'pdf', .xlsx set 'xlsx' etc.
     */
    public function performDownload(string $id, string $type): \yii\web\Response {
        $baseUrl = $this->serverUrl();
        $url = "{$baseUrl}api/v1/download?id={$id}&type={$type}";
        Yii::debug($url, __METHOD__);

        $token = $this->getClient()->loadServiceToken();

        $ch = curl_init($url);

        $curlHeaders = [
            'Service-Authorization: ' . $token,
        ];

        if (Yii::$app->user !== null && Yii::$app->user->identity !== null) {
            $curlHeaders[] = 'Authorization: ' . Yii::$app->user->identity->authToken;
        }

        // Capture response headers
        $responseHeaders = [];

        curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($ch, $header) use (&$responseHeaders) {
            $len = strlen($header);

            $parts = explode(':', $header, 2);
            if (count($parts) === 2) {
                $name = strtolower(trim($parts[0]));
                $value = trim($parts[1]);

                // overwrite so we keep final response headers after redirects
                $responseHeaders[$name] = $value;
            }

            return $len;
        });

        // Open temp stream
        $stream = fopen('php://temp', 'w+');

        curl_setopt_array($ch, [
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_RETURNTRANSFER => false,
            CURLOPT_HTTPHEADER => $curlHeaders,
            CURLOPT_FILE => $stream,
        ]);

        curl_exec($ch);

        if (curl_errno($ch)) {
            /**
             * When php 8.5, this is deprecated, just call unset() on $ch
             */
            curl_close($ch);
            fclose($stream);
            throw new NotFoundHttpException('File not found.');
        }

        /**
         * When php 8.5, this is deprecated, just call unset() on $ch
         */
        curl_close($ch);

        rewind($stream);

        // ---- Extract filename from Content-Disposition ----
        $filename = 'data-report.' . $type; // fallback

        if (!empty($responseHeaders['content-disposition'])) {
            $disposition = $responseHeaders['content-disposition'];

            // Prefer RFC 5987 (filename*)
            if (preg_match('/filename\*\s*=\s*UTF-8\'\'([^;]+)/i', $disposition, $matches)) {
                $filename = rawurldecode(trim($matches[1], "\"'"));
            }
            // Fallback to basic filename=
            elseif (preg_match('/filename\s*=\s*"([^"]+)"/i', $disposition, $matches)) {
                $filename = $matches[1];
            } elseif (preg_match('/filename\s*=\s*([^;]+)/i', $disposition, $matches)) {
                $filename = trim($matches[1], "\"'");
            }
        }

        // ---- Determine mime type ----
        $mimeType = $responseHeaders['content-type'] ?? 'application/octet-stream';

        return Yii::$app->response->sendStreamAsFile(
            $stream,
            $filename,
            [
                'mimeType' => $mimeType,
                'inline' => false,
            ]
        );
    }
}
