<?php
declare(strict_types=1);
error_reporting(0);
ini_set('display_errors', 0);


// // Display all PHP errors
// error_reporting(E_ALL);

// // Show errors in browser/output
// ini_set('display_errors', 1);
// ini_set('display_startup_errors', 1);

$origin = $_SERVER['HTTP_ORIGIN'] ?? '*';
header('Vary: Origin');
header('Access-Control-Allow-Origin: ' . $origin);
// If you use cookies/auth credentials from browser, do NOT use "*" above.
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With, Accept, Origin');
header('Access-Control-Max-Age: 86400');
// Handle preflight request quickly
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(204);
    exit;
}
/**
 * wfm_proxy.php
 *
 * One-file proxy for WFM APIs:
 * - Auth flow: Encrypt -> Login/authenticate -> JWT
 * - Routes multiple commands to remote endpoints
 * - Reads input from GET/POST (and multipart for SaveMeterReplacement)
 * - Returns upstream response body as-is (JSON/text), with upstream status code
 *
 * Example:
 *   /wfm_proxy.php?cmd=hes_status&msn=FIOR034426016801ON
 *
 * Usage:

 * ?cmd=meter_validation&msn=FIOR034426016801
 * ?cmd=retrofit_mapping&msn=FIOR034426016801
 * ?cmd=meter_communication_status&msn=FIOR034426016801
 * ?cmd=meter_dropdown_details (or pass &token=...)
 * ?cmd=meter_installation_details&PageNo=1&PageSize=10
 * ?cmd=consumer_survey_details&PageNo=1&PageSize=5000
 * ?cmd=save_meter_replacement with multipart POST fields/files (smart meter replacement).
 * ?cmd=save_meter_retrofit_installation with multipart POST fields/files (GCZ retrofit).
 */

/* ------------------------ CONFIG ------------------------ */
const WFM_BASE = 'https://wfm-api.smartazerigas.az/api';//'https://wfmapi-idp.smartgasconnect.ai/api';
#const ENC_URL  = 'http://cportalgasapi.esyasoft.com/api/Admin/Encrypt';

const DEFAULT_INSTALLER_EMAIL = 'wfm-int@predsol.az';

const INSTALLER_PASSWORD = 'Fydtryugsp@6754';
const DEVICE_ID = '20eac877c388fb8c';
const DEVICE_MODEL = 'sdk_gphone64_x86_64';

/* ------------------------ OUTPUT HELPERS ------------------------ */
// function resolveInstallerEmail(): string
// {
//     // check common keys from GET/POST/JSON payload style
//     $email = $_REQUEST['installerEmail'] ?? $_REQUEST['InstallerId'] ?? $_REQUEST['UserName'] ?? '';
//     $email = is_string($email) ? trim($email) : '';
//     return $email !== '' ? $email : DEFAULT_INSTALLER_EMAIL;
// }

function resolveInstallerEmail(): string
{
    return DEFAULT_INSTALLER_EMAIL;
}

function respondError(int $status, string $message, array $extra = []): void
{
    http_response_code($status);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode(array_merge(['error' => $message], $extra), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

function outputUpstream(array $res): void
{
    $status = $res['status'] ?? 500;
    $ctype  = $res['content_type'] ?? 'application/json; charset=utf-8';
    http_response_code($status);
    header('Content-Type: ' . $ctype);
    echo (string)($res['body'] ?? '');
    exit;
}

/* ------------------------ HTTP HELPERS ------------------------ */
function curlRequest(
    string $url,
    string $method = 'GET',
    array $headers = [],
    $body = null,
    bool $isMultipart = false
): array {
    
    // // LOG REQUEST AND STOP EXECUTION
    // header('Content-Type: application/json; charset=utf-8');

    // echo json_encode([
    //     'request' => [
    //         'url' => $url,
    //         'method' => strtoupper($method),
    //         'headers' => $headers,
    //         'body' => $body,
    //         'isMultipart' => $isMultipart,
    //     ]
    // ], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

    // die();

    $ch = curl_init($url);
    if ($ch === false) {
        return ['status' => 500, 'body' => '{"error":"curl_init failed"}', 'content_type' => 'application/json'];
    }

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($method));
    curl_setopt($ch, CURLOPT_TIMEOUT, 60);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_HEADER, true);

    if (!empty($headers)) {
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    }

    if ($body !== null) {
        if ($isMultipart) {
            curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
        } else {
            curl_setopt($ch, CURLOPT_POSTFIELDS, is_string($body) ? $body : json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
        }
    }

    $raw = curl_exec($ch);
    if ($raw === false) {
        $err = curl_error($ch);
        $errno = curl_errno($ch);
        curl_close($ch);
        
        return ['status' => 502, 'body' => json_encode([
            'error' => 'cURL error',
            'details' => $err,
            'url' => $url,
            'method' => strtoupper($method),
            'curl_errno' => $errno,
        ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), 'content_type' => 'application/json'];
    }
    

    $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $status = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $contentType = (string)(curl_getinfo($ch, CURLINFO_CONTENT_TYPE) ?: 'application/json; charset=utf-8');
    curl_close($ch);

    return [
        'status' => $status,
        'body' => substr($raw, $headerSize),
        'content_type' => $contentType,
    ];
}

function requireParam(string $name): string
{
    $v = $_REQUEST[$name] ?? '';
    if (!is_string($v) || trim($v) === '') {
        respondError(400, "Missing required parameter: {$name}");
    }
    return trim($v);
}

/* ------------------------ AUTH FLOW ------------------------ */
function getEncryptedPassword(string $plain): string
{
    $res = curlRequest(
        WFM_BASE . '/Admin/Encrypt',
        'GET',
        [
            'plaintext: ' . $plain,
            'Accept: application/json',
        ]
    );

    if (($res['status'] ?? 500) >= 400) {
        respondError(502, 'Encrypt endpoint failed', ['upstream_status' => $res['status'], 'upstream_body' => $res['body']]);
    }

    $json = json_decode((string)$res['body'], true);
    // print_r($json);
    // die(0);
    if (!is_array($json) || empty($json['value'])) {
        respondError(502, 'Encrypt endpoint returned invalid response', ['upstream_body' => $res['body']]);
    }

    return (string)$json['value'];
}

// function getJwtToken(string $installerEmail): string
// {
//     if (!isset(INSTALLER_CREDENTIALS[$installerEmail])) {
//         respondError(400, 'Installer email not mapped to password', ['installerEmail' => $installerEmail]);
//     }

//     $plainPassword = INSTALLER_CREDENTIALS[$installerEmail];
//     $encrypted = getEncryptedPassword($plainPassword);

//     $ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
//     $payload = [
//         'Username'    => $installerEmail,
//         'Password'    => $encrypted,
//         'DeviceId'    => DEVICE_ID,
//         'IpAddress'   => $ip,
//         'DeviceModel' => DEVICE_MODEL,
//     ];

//     $res = curlRequest(
//         WFM_BASE . '/Login/authenticate',
//         'POST',
//         [
//             'Content-Type: application/json',
//             'Accept: application/json, text/plain, */*',
//             'Accept-Encoding: gzip',
//             'Accept-Language: en',
//             'User-Agent: okhttp/4.9.2',
//         ],
//         $payload
//     );

//     if (($res['status'] ?? 500) >= 400) {
//         respondError(502, 'Authentication failed', [
//             'installerEmail' => $installerEmail,
//             'upstream_status' => $res['status'],
//             'upstream_body' => $res['body']
//         ]);
//     }

//     $json = json_decode((string)$res['body'], true);
//     if (!is_array($json) || empty($json['jwtToken'])) {
//         respondError(502, 'Authentication response missing jwtToken', ['upstream_body' => $res['body']]);
//     }

//     return (string)$json['jwtToken'];
// }

/** Reuse JWT across proxy requests; re-login only after upstream HTTP 401. */
const WFM_JWT_CACHE_TTL_SEC = 82800; // 23h

function isUnauthorizedUpstream(array $res): bool
{
    return (int)($res['status'] ?? 0) === 401;
}

function getJwtTokenFresh(string $installerEmail): string
{
    $encrypted = getEncryptedPassword(INSTALLER_PASSWORD);

    $ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';

    $payload = [
        'Username'    => DEFAULT_INSTALLER_EMAIL,
        'Password'    => $encrypted,
        'DeviceId'    => DEVICE_ID,
        'IpAddress'   => $ip,
        'DeviceModel' => DEVICE_MODEL,
    ];

    $res = curlRequest(
        WFM_BASE . '/Login/authenticate',
        'POST',
        [
            'Content-Type: application/json',
            'Accept: application/json, text/plain, */*',
            'Accept-Encoding: gzip',
            'Accept-Language: en',
            'User-Agent: okhttp/4.9.2',
        ],
        $payload
    );

    if (($res['status'] ?? 500) >= 400) {
        respondError(502, 'Authentication failed', [
            'installerEmail' => DEFAULT_INSTALLER_EMAIL,
            'upstream_status' => $res['status'],
            'upstream_body' => $res['body']
        ]);
    }

    $json = json_decode((string)$res['body'], true);

    if (!is_array($json) || empty($json['jwtToken'])) {
        respondError(502, 'Authentication response missing jwtToken', [
            'upstream_body' => $res['body']
        ]);
    }

    return (string)$json['jwtToken'];
}

function getJwtTokenCached(string $installerEmail, bool $forceRefresh = false): string
{
    static $cache = ['token' => '', 'at' => 0];
    $now = time();
    if (
        !$forceRefresh
        && $cache['token'] !== ''
        && ($now - $cache['at']) < WFM_JWT_CACHE_TTL_SEC
    ) {
        return $cache['token'];
    }
    $token = getJwtTokenFresh($installerEmail);
    $cache['token'] = $token;
    $cache['at'] = $now;
    return $token;
}

/**
 * @param array<int, string> $extraHeaders
 */
function curlRequestAuthed(
    string $installerEmail,
    string $url,
    string $method = 'GET',
    array $extraHeaders = [],
    $body = null,
    bool $isMultipart = false
): array {
    $token = getJwtTokenCached($installerEmail);
    $headers = array_merge(['Authorization: Bearer ' . $token], $extraHeaders);
    $res = curlRequest($url, $method, $headers, $body, $isMultipart);
    if (isUnauthorizedUpstream($res)) {
        $token = getJwtTokenCached($installerEmail, true);
        $headers = array_merge(['Authorization: Bearer ' . $token], $extraHeaders);
        $res = curlRequest($url, $method, $headers, $body, $isMultipart);
    }
    return $res;
}

/* ------------------------ MULTIPART BUILD ------------------------ */
function buildMultipartPayload(): array
{
    $post = $_POST;
    $files = [];

    foreach ($_FILES as $field => $info) {
        if (!isset($info['tmp_name'])) {
            continue;
        }

        // single file
        if (is_string($info['tmp_name']) && is_uploaded_file($info['tmp_name'])) {
            $mime = $info['type'] ?? 'application/octet-stream';
            $name = $info['name'] ?? basename($info['tmp_name']);
            $files[$field] = new CURLFile($info['tmp_name'], $mime, $name);
            continue;
        }

        // multiple files
        if (is_array($info['tmp_name'])) {
            foreach ($info['tmp_name'] as $i => $tmp) {
                if (!is_string($tmp) || !is_uploaded_file($tmp)) continue;
                $mime = $info['type'][$i] ?? 'application/octet-stream';
                $name = $info['name'][$i] ?? basename($tmp);
                $files["{$field}[{$i}]"] = new CURLFile($tmp, $mime, $name);
            }
        }
    }

    return array_merge($post, $files);
}

/* ------------------------ ROUTER ------------------------ */
$cmd = strtolower((string)($_REQUEST['cmd'] ?? ''));
if ($cmd === '') {
    respondError(400, 'Missing cmd parameter');
}

$installerEmail = resolveInstallerEmail(); // default gp_ealiyev..., override if installerEmail exists

switch ($cmd) {
    // 1) MeterValidation?msn=...
    case 'meter_validation': {
        $msn = requireParam('msn');
        $res = curlRequestAuthed(
            $installerEmail,
            WFM_BASE . '/Meter/MeterValidation?msn=' . rawurlencode($msn),
            'GET'
        );
        outputUpstream($res); // returns plain text "Not installed" etc.
    }

    // 2) RetrofitMapping?msn=...
    case 'retrofit_mapping': {
        $msn = requireParam('msn');
        $res = curlRequestAuthed(
            $installerEmail,
            WFM_BASE . '/Meter/RetrofitMapping?msn=' . rawurlencode($msn),
            'GET'
        );
        outputUpstream($res);
    }

    // 3) SaveMeterReplacement (multipart/form-data)
    case 'save_meter_replacement': {
        $saveInstaller = resolveInstallerEmail();
        $multipart = buildMultipartPayload();

        // optional safety: if not supplied by caller, stamp installer-related fields
        if (!isset($multipart['InstalledBy']) || trim((string)$multipart['InstalledBy']) === '') {
            $multipart['InstalledBy'] = $saveInstaller;
        }
        if (!isset($multipart['InstallationId']) || trim((string)$multipart['InstallationId']) === '') {
            $installationId = trim((string)($_REQUEST['InstallationId'] ?? $_REQUEST['installationId'] ?? ''));
            if ($installationId !== '') {
                $multipart['InstallationId'] = $installationId;
            }
        }

        $res = curlRequestAuthed(
            $saveInstaller,
            WFM_BASE . '/Meter/SaveMeterReplacement',
            'POST',
            [],
            $multipart,
            true
        );
        outputUpstream($res);
    }

    // 3b) Retrofit SaveMeterInstallation (multipart/form-data)
    case 'save_meter_retrofit_installation': {
        $saveInstaller = resolveInstallerEmail();
        $multipart = buildMultipartPayload();

        if (!isset($multipart['InstalledBy']) || trim((string)$multipart['InstalledBy']) === '') {
            $multipart['InstalledBy'] = $saveInstaller;
        }
        if (!isset($multipart['InstallationId']) || trim((string)$multipart['InstallationId']) === '') {
            $installationId = trim((string)($_REQUEST['InstallationId'] ?? $_REQUEST['installationId'] ?? ''));
            if ($installationId !== '') {
                $multipart['InstallationId'] = $installationId;
            }
        }

        $res = curlRequestAuthed(
            $saveInstaller,
            WFM_BASE . '/Meter/Retrofit/SaveMeterInstallation',
            'POST',
            [],
            $multipart,
            true
        );
        outputUpstream($res);
    }

    // 4) MeterInstallation/details (JSON POST)
    case 'meter_installation_details': {
        $payload = [
            'InstallerId'   => (string)($_REQUEST['InstallerId'] ?? DEFAULT_INSTALLER_EMAIL),
            'Is_Installed'  => filter_var($_REQUEST['Is_Installed'] ?? 'false', FILTER_VALIDATE_BOOLEAN),
            'Consno'        => (string)($_REQUEST['Consno'] ?? '-1'),
            'PageNo'        => (int)($_REQUEST['PageNo'] ?? 1),
            'PageSize'      => (int)($_REQUEST['PageSize'] ?? 10),
        ];
        $res = curlRequestAuthed(
            $installerEmail,
            WFM_BASE . '/Meter/MeterInstallation/details',
            'POST',
            ['Content-Type: application/json'],
            $payload
        );
        outputUpstream($res);
    }

    // 5) MeterCommunicationStatus?Msn=...
    case 'meter_communication_status': {
        $msn = requireParam('msn');
        $res = curlRequestAuthed(
            $installerEmail,
            WFM_BASE . '/Meter/MeterCommunicationStatus?Msn=' . rawurlencode($msn),
            'GET'
        );
        outputUpstream($res);
    }

    // 6) Consumer/MeterDropDownList/details?token=...
    case 'meter_dropdown_details': {
        $tokenParam = (string)($_REQUEST['token'] ?? getJwtTokenCached($installerEmail));
        $res = curlRequestAuthed(
            $installerEmail,
            WFM_BASE . '/Consumer/MeterDropDownList/details?token=' . rawurlencode($tokenParam),
            'GET'
        );
        outputUpstream($res);
    }

    // 7) Consumer/ConsumerSurvey/Details (JSON POST)
    case 'consumer_survey_details': {
        $payload = [
            'token'      => (string)($_REQUEST['token'] ?? getJwtTokenCached($installerEmail)),
            'ConsumerNo' => (string)($_REQUEST['ConsumerNo'] ?? '-1'),
            'UserName'   => (string)($_REQUEST['UserName'] ?? DEFAULT_INSTALLER_EMAIL),
            'PageNo'     => (int)($_REQUEST['PageNo'] ?? 1),
            'PageSize'   => (int)($_REQUEST['PageSize'] ?? 5000),
            'Msn'        => (string)($_REQUEST['Msn'] ?? '-1'),
        ];
        $res = curlRequestAuthed(
            $installerEmail,
            WFM_BASE . '/Consumer/ConsumerSurvey/Details',
            'POST',
            ['Content-Type: application/json'],
            $payload
        );
        outputUpstream($res);
    }

    // 8) Initial HesCommunicationStatus?msn=...
    case 'hes_communication_status': {
        $msn = requireParam('msn');
        $res = curlRequestAuthed(
            $installerEmail,
            WFM_BASE . '/Meter/HesCommunicationStatus?msn=' . rawurlencode($msn),
            'GET'
        );
        outputUpstream($res);
    }
    default:
        respondError(400, 'Unknown cmd', [
            'allowed_cmds' => [
                'meter_validation',
                'retrofit_mapping',
                'save_meter_replacement',
                'save_meter_retrofit_installation',
                'meter_installation_details',
                'meter_communication_status',
                'meter_dropdown_details',
                'consumer_survey_details',
                'hes_communication_status'
            ],
        ]);
}