<?php
/**
 * steadfast.php - Steadfast API কল (সার্ভার থেকে cURL - তাই ব্লক হয় না)
 */
require_once __DIR__ . '/config.php';

function steadfastRequest($apiKey, $secretKey, $method, $path, $body = null) {
    $url = STEADFAST_BASE_URL . $path;
    $ch = curl_init($url);
    $headers = [
        'Api-Key: ' . $apiKey,
        'Secret-Key: ' . $secretKey,
        'Content-Type: application/json'
    ];
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    if ($body !== null && in_array($method, ['POST', 'PUT'])) {
        curl_setopt($ch, CURLOPT_POSTFIELDS, is_string($body) ? $body : json_encode($body));
    }
    $response = curl_exec($ch);
    $err = curl_error($ch);
    $httpCode = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    if ($err) {
        return ['ok' => false, 'http_code' => $httpCode, 'error' => $err];
    }
    $decoded = json_decode($response, true);
    if (!is_array($decoded)) {
        return ['ok' => $httpCode >= 200 && $httpCode < 300, 'http_code' => $httpCode, 'raw' => $response];
    }
    $decoded['ok'] = $httpCode >= 200 && $httpCode < 300;
    $decoded['http_code'] = $httpCode;
    return $decoded;
}

function steadfastCreateOrder($apiKey, $secretKey, $data) {
    return steadfastRequest($apiKey, $secretKey, 'POST', '/create_order', $data);
}

function steadfastBulkOrder($apiKey, $secretKey, $dataArray) {
    return steadfastRequest($apiKey, $secretKey, 'POST', '/create_order/bulk-order', ['data' => $dataArray]);
}

function steadfastStatusByCid($apiKey, $secretKey, $id) {
    return steadfastRequest($apiKey, $secretKey, 'GET', '/status_by_cid/' . urlencode($id));
}

function steadfastStatusByInvoice($apiKey, $secretKey, $invoice) {
    return steadfastRequest($apiKey, $secretKey, 'GET', '/status_by_invoice/' . urlencode($invoice));
}

function steadfastStatusByTracking($apiKey, $secretKey, $code) {
    return steadfastRequest($apiKey, $secretKey, 'GET', '/status_by_trackingcode/' . urlencode($code));
}

function steadfastGetBalance($apiKey, $secretKey) {
    return steadfastRequest($apiKey, $secretKey, 'GET', '/get_balance');
}

function steadfastCreateReturn($apiKey, $secretKey, $data) {
    return steadfastRequest($apiKey, $secretKey, 'POST', '/create_return_request', $data);
}

function steadfastGetReturnRequests($apiKey, $secretKey) {
    return steadfastRequest($apiKey, $secretKey, 'GET', '/get_return_requests');
}

function steadfastGetPayments($apiKey, $secretKey) {
    return steadfastRequest($apiKey, $secretKey, 'GET', '/payments');
}

function steadfastGetPaymentById($apiKey, $secretKey, $paymentId) {
    return steadfastRequest($apiKey, $secretKey, 'GET', '/payments/' . urlencode($paymentId));
}

function steadfastGetReturnRequest($apiKey, $secretKey, $id) {
    return steadfastRequest($apiKey, $secretKey, 'GET', '/get_return_request/' . urlencode($id));
}

function steadfastGetPoliceStations($apiKey, $secretKey) {
    return steadfastRequest($apiKey, $secretKey, 'GET', '/police_stations');
}

/**
 * GET request with query string (for list/discovery endpoints).
 */
function steadfastGetWithQuery($apiKey, $secretKey, $path, array $query = []) {
    $qs = $query ? ('?' . http_build_query($query)) : '';
    return steadfastRequest($apiKey, $secretKey, 'GET', $path . $qs);
}

function steadfastLooksLikeConsignmentRows($arr) {
    if (!is_array($arr) || $arr === []) {
        return false;
    }
    $keys = array_keys($arr);
    if ($keys !== range(0, count($arr) - 1)) {
        return false;
    }
    $first = $arr[0];
    if (!is_array($first)) {
        return false;
    }
    return isset($first['tracking_code']) || isset($first['consignment_id']) || isset($first['invoice'])
        || isset($first['status']) || isset($first['delivery_status']);
}

/**
 * Extract list + meta from various Steadfast/courier payload shapes.
 *
 * @return array{items: array<int,array>, meta: mixed, parse_mode: string}
 */
function steadfastExtractConsignmentListFromPayload(array $payload) {
    $nestedKeys = ['data', 'consignments', 'orders', 'items', 'list', 'results', 'rows', 'parcel_list'];
    foreach ($nestedKeys as $k) {
        if (isset($payload[$k]) && is_array($payload[$k]) && steadfastLooksLikeConsignmentRows($payload[$k])) {
            return [
                'items' => $payload[$k],
                'meta' => $payload['meta'] ?? $payload['pagination'] ?? $payload['links'] ?? null,
                'parse_mode' => 'nested:' . $k,
            ];
        }
    }
    if (steadfastLooksLikeConsignmentRows($payload)) {
        return ['items' => $payload, 'meta' => null, 'parse_mode' => 'root_array'];
    }
    return ['items' => [], 'meta' => null, 'parse_mode' => 'none'];
}

function steadfastResponseIndicatesNotFound(array $result) {
    $code = isset($result['http_code']) ? (int) $result['http_code'] : 0;
    if ($code === 404) {
        return true;
    }
    $msg = strtolower((string) ($result['message'] ?? ''));
    if (strpos($msg, 'not found') !== false || strpos($msg, 'no route') !== false) {
        return true;
    }
    return false;
}

/**
 * Try multiple GET paths; first successful parse wins.
 *
 * @return array{success:bool, items:array, meta:mixed, endpoint:string|null, http_code:int, parse_mode:string, raw:array|null}
 */
function steadfastDiscoverConsignmentList($apiKey, $secretKey, array $query) {
    $candidates = [
        '/consignments',
        '/get_consignments',
        '/merchant/consignments',
        '/order_list',
        '/orders',
        '/my_consignment',
        '/consignment_list',
    ];
    $last = null;
    foreach ($candidates as $path) {
        $result = steadfastGetWithQuery($apiKey, $secretKey, $path, $query);
        $last = $result;
        $friendly = steadfastFriendlyMessage($result);
        if ($friendly !== null) {
            return [
                'success' => false,
                'items' => [],
                'meta' => null,
                'endpoint' => $path,
                'http_code' => (int) ($result['http_code'] ?? 0),
                'parse_mode' => 'friendly_error',
                'raw' => $result,
                'friendly' => $friendly,
            ];
        }
        if (!empty($result['error'])) {
            continue;
        }
        if (steadfastResponseIndicatesNotFound($result)) {
            continue;
        }
        $extract = steadfastExtractConsignmentListFromPayload($result);
        if ($extract['items'] !== []) {
            return [
                'success' => true,
                'items' => $extract['items'],
                'meta' => $extract['meta'],
                'endpoint' => $path,
                'http_code' => (int) ($result['http_code'] ?? 0),
                'parse_mode' => $extract['parse_mode'],
                'raw' => null,
                'friendly' => null,
            ];
        }
    }
    return [
        'success' => false,
        'items' => [],
        'meta' => null,
        'endpoint' => null,
        'http_code' => $last ? (int) ($last['http_code'] ?? 0) : 0,
        'parse_mode' => 'none',
        'raw' => $last,
        'friendly' => null,
    ];
}

/**
 * Flatten consignment-like arrays from a payment detail payload.
 *
 * @return array<int,array>
 */
function steadfastExtractConsignmentsFromPaymentDetail(array $detail) {
    $out = [];
    $keys = ['consignments', 'data', 'items', 'parcels'];
    foreach ($keys as $k) {
        if (isset($detail[$k]) && is_array($detail[$k])) {
            foreach ($detail[$k] as $row) {
                if (is_array($row)) {
                    $out[] = $row;
                }
            }
        }
    }
    if ($out === [] && isset($detail['consignment']) && is_array($detail['consignment'])) {
        $out[] = $detail['consignment'];
    }
    if ($out === [] && steadfastLooksLikeConsignmentRows($detail)) {
        return $detail;
    }
    return $out;
}

/**
 * Fallback: GET /payments then GET /payments/{id} (limited) to collect consignment rows.
 *
 * @return array{success:bool, items:array<int,array>, payments_scanned:int, endpoint:string, http_code:int, parse_mode:string}
 */
function steadfastConsignmentsFromPaymentsFallback($apiKey, $secretKey, $maxPaymentDetails = 20) {
    $list = steadfastGetPayments($apiKey, $secretKey);
    $friendly = steadfastFriendlyMessage($list);
    if ($friendly !== null) {
        return [
            'success' => false,
            'items' => [],
            'payments_scanned' => 0,
            'endpoint' => '/payments',
            'http_code' => (int) ($list['http_code'] ?? 0),
            'parse_mode' => 'payments_error',
            'friendly' => $friendly,
        ];
    }
    $payments = [];
    if (isset($list['data']) && is_array($list['data'])) {
        $payments = $list['data'];
    } elseif (steadfastLooksLikeConsignmentRows($list)) {
        // Unlikely; treat as empty for fallback path
        $payments = [];
    } elseif (is_array($list)) {
        $numeric = array_values($list);
        if (isset($numeric[0]) && is_array($numeric[0]) && (isset($numeric[0]['id']) || isset($numeric[0]['payment_id']))) {
            $payments = $numeric;
        }
    }
    $seen = [];
    $items = [];
    $n = 0;
    foreach ($payments as $p) {
        if ($n >= $maxPaymentDetails) {
            break;
        }
        if (!is_array($p)) {
            continue;
        }
        $pid = $p['id'] ?? $p['payment_id'] ?? null;
        if ($pid === null || $pid === '') {
            continue;
        }
        $detail = steadfastGetPaymentById($apiKey, $secretKey, (string) $pid);
        if (!empty($detail['error']) || steadfastFriendlyMessage($detail)) {
            $n++;
            continue;
        }
        $rows = steadfastExtractConsignmentsFromPaymentDetail($detail);
        foreach ($rows as $row) {
            if (!is_array($row)) {
                continue;
            }
            $key = ($row['tracking_code'] ?? '') . '|' . ($row['consignment_id'] ?? $row['id'] ?? '') . '|' . ($row['invoice'] ?? '');
            if ($key === '||') {
                continue;
            }
            if (isset($seen[$key])) {
                continue;
            }
            $seen[$key] = true;
            $items[] = $row;
        }
        $n++;
    }
    return [
        'success' => $items !== [],
        'items' => $items,
        'payments_scanned' => $n,
        'endpoint' => '/payments+/payments/{id}',
        'http_code' => (int) ($list['http_code'] ?? 200),
        'parse_mode' => 'payments_fallback',
        'friendly' => null,
    ];
}

/**
 * Aggregate consignment rows: discovery first, then payments fallback.
 *
 * @return array{
 *   success: bool,
 *   items: array,
 *   source: string,
 *   endpoint: string|null,
 *   http_code: int,
 *   parse_mode: string,
 *   integration_not_supported: bool,
 *   message: string|null,
 *   payments_scanned: int
 * }
 */
function steadfastFetchConsignmentsAggregated($apiKey, $secretKey, array $query) {
    $disc = steadfastDiscoverConsignmentList($apiKey, $secretKey, $query);
    if (!empty($disc['friendly'])) {
        return [
            'success' => false,
            'items' => [],
            'source' => 'discovery',
            'endpoint' => $disc['endpoint'],
            'http_code' => $disc['http_code'],
            'parse_mode' => $disc['parse_mode'],
            'integration_not_supported' => false,
            'message' => null,
            'payments_scanned' => 0,
            'friendly' => $disc['friendly'],
        ];
    }
    if ($disc['success'] && $disc['items'] !== []) {
        return [
            'success' => true,
            'items' => $disc['items'],
            'source' => 'discovery',
            'endpoint' => $disc['endpoint'],
            'http_code' => $disc['http_code'],
            'parse_mode' => $disc['parse_mode'],
            'integration_not_supported' => false,
            'message' => null,
            'payments_scanned' => 0,
            'friendly' => null,
        ];
    }
    $fb = steadfastConsignmentsFromPaymentsFallback($apiKey, $secretKey, 25);
    if (!empty($fb['friendly'])) {
        return [
            'success' => false,
            'items' => [],
            'source' => 'payments_fallback',
            'endpoint' => $fb['endpoint'],
            'http_code' => $fb['http_code'],
            'parse_mode' => $fb['parse_mode'],
            'integration_not_supported' => false,
            'message' => null,
            'payments_scanned' => $fb['payments_scanned'],
            'friendly' => $fb['friendly'],
        ];
    }
    if ($fb['success'] && $fb['items'] !== []) {
        return [
            'success' => true,
            'items' => $fb['items'],
            'source' => 'payments_fallback',
            'endpoint' => $fb['endpoint'],
            'http_code' => $fb['http_code'],
            'parse_mode' => $fb['parse_mode'],
            'integration_not_supported' => false,
            'message' => 'তালিকা পেমেন্ট API থেকে সংগৃহীত (সম্পূর্ণ নাও হতে পারে)।',
            'payments_scanned' => $fb['payments_scanned'],
            'friendly' => null,
        ];
    }
    return [
        'success' => false,
        'items' => [],
        'source' => 'none',
        'endpoint' => null,
        'http_code' => $disc['http_code'] ?: ($fb['http_code'] ?? 0),
        'parse_mode' => 'unsupported',
        'integration_not_supported' => true,
        'message' => 'Courier API থেকে সরাসরি অর্ডার তালিকা পাওয়া যায়নি। Steadfast ডকুমেন্টেশন অনুযায়ী list endpoint থাকলে সাপোর্টে নিশ্চিত করুন। একক ট্র্যাকিং/ইনভয়েস দিয়ে Status পেজ ব্যবহার করুন।',
        'payments_scanned' => $fb['payments_scanned'] ?? 0,
        'friendly' => null,
    ];
}

/** API রেসপন্সে "Account is not active" থাকলে সেটা চেক করে ইউজার-বান্ধব মেসেজ দেয় */
function steadfastFriendlyMessage($result) {
    $raw = isset($result['raw']) ? (is_string($result['raw']) ? $result['raw'] : json_encode($result['raw'])) : '';
    $message = isset($result['message']) && is_string($result['message']) ? $result['message'] : '';
    $error = isset($result['error']) && is_string($result['error']) ? $result['error'] : '';
    $haystack = strtolower($raw . ' ' . $message . ' ' . $error);
    if (stripos($raw, 'Account is not active') !== false) {
        return [
            'success' => false,
            'message' => 'আপনার Steadfast অ্যাকাউন্ট এখনও অ্যাক্টিভ হয়নি। অ্যাকাউন্ট অ্যাক্টিভ হলে সব ডাটা দেখা যাবে। Steadfast সাপোর্টে যোগাযোগ করুন।',
            'account_inactive' => true
        ];
    }
    if (strpos($haystack, 'unauthorized') !== false || strpos($haystack, 'invalid api') !== false || strpos($haystack, 'forbidden') !== false) {
        return ['success' => false, 'message' => 'API Key বা Secret Key ভুল। Settings থেকে সঠিক Key দিন।', 'auth_error' => true];
    }
    if (strpos($haystack, 'already exists') !== false || strpos($haystack, 'duplicate') !== false || strpos($haystack, 'invoice') !== false && strpos($haystack, 'exist') !== false) {
        return ['success' => false, 'message' => 'এই Invoice আগে থেকেই আছে। নতুন Invoice দিয়ে চেষ্টা করুন।', 'duplicate_invoice' => true];
    }
    if (strpos($haystack, 'timed out') !== false || strpos($haystack, 'timeout') !== false) {
        return ['success' => false, 'message' => 'Courier API টাইমআউট হয়েছে। একটু পরে আবার চেষ্টা করুন।', 'timeout' => true];
    }
    if (strpos($haystack, 'recipient_phone') !== false || strpos($haystack, 'validation') !== false) {
        return ['success' => false, 'message' => 'অর্ডারের কিছু তথ্য সঠিক নয়। ফোন, ঠিকানা, বা ডেলিভারি টাইপ চেক করুন।', 'validation_error' => true];
    }
    return null;
}

function normalizeCreateOrderResult($result) {
    $friendly = steadfastFriendlyMessage($result);
    if ($friendly !== null) {
        $friendly['raw'] = $result;
        return $friendly;
    }

    $consignment = isset($result['consignment']) && is_array($result['consignment']) ? $result['consignment'] : null;
    $ok = !empty($result['ok']);
    $httpCode = isset($result['http_code']) ? (int) $result['http_code'] : 0;
    $hasTracking = $consignment && !empty($consignment['tracking_code']);
    $success = ($ok && $hasTracking) || (isset($result['status']) && (int) $result['status'] === 200 && $hasTracking);

    if ($success) {
        return [
            'success' => true,
            'message' => 'অর্ডার সফল হয়েছে।',
            'tracking_code' => (string) ($consignment['tracking_code'] ?? ''),
            'consignment_id' => (string) ($consignment['consignment_id'] ?? ''),
            'status_text' => (string) ($consignment['status'] ?? ''),
            'http_code' => $httpCode,
            'raw' => $result
        ];
    }

    return [
        'success' => false,
        'message' => (string) ($result['message'] ?? $result['error'] ?? 'Courier API order create ব্যর্থ হয়েছে।'),
        'tracking_code' => '',
        'consignment_id' => '',
        'status_text' => '',
        'http_code' => $httpCode,
        'raw' => $result
    ];
}
?>
