<?php

namespace api\modules\v1\controllers;

use api\components\Controller;
use common\models\ApiToken;
use Yii;
use common\models\HisRequest;
use common\models\LisApiD;
use common\models\LisApiSend;
use common\models\LisResult;
use common\models\LisResultSend;
use common\models\RiaFrmDVlab;
use common\models\RiaFrmHVLAB;
use common\models\RiaLabD;
use DateTime;
use finfo;
use OpenApi\Annotations as OA;
use yii\helpers\Json;

/**
 * @OA\Tag(
 *   name="LisResult",
 *   description="LIS Result endpoints"
 * )
 */
class LisResultControllerOldTwo extends Controller
{

    /**
     * @OA\Get(
     *   path="/lis-result",
     *   summary="Get list LIS Result",
     *   operationId="LisResultIndex",
     *   tags={"LisResult"},
     *   security={{"bearerAuth": {}}},
     *   @OA\Response(
     *     response=200,
     *     description="OK",
     *     @OA\JsonContent(
     *       type="object",
     *       @OA\Property(property="count", type="integer", example=10),
     *       @OA\Property(
     *         property="dataModels",
     *         type="array",
     *         @OA\Items(ref="#/components/schemas/LisResult")
     *       ),
     *       @OA\Property(property="total", type="integer", example=100)
     *     )
     *   ),
     *   @OA\Response(
     *     response=401,
     *     description="Unauthorized",
     *     @OA\JsonContent(ref="#/components/schemas/Unauthorized")
     *   )
     * )
     */

    // === แทนที่ method ที่เกี่ยวข้องทั้งหมดด้วยโค้ดด้านล่าง ===

    /**
     * actionCreate (แก้ไข) - คืนค่า JSON
     */
    public function actionCreate()
    {
        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        // ===== ดึงข้อมูล Lab =====
        $RiaLabD = LisApiD::find()
            ->where(['RiaLDApprvFlag' => '1'])
            ->orderBy(['RiaHDocDate' => SORT_DESC])
            ->all();

        $groupedByLabNo = [];
        $sendMapping = [];
        $globalDebug = [];

        foreach ($RiaLabD as $rows) {
            $riaH = RiaFrmHVLAB::findOne(['RiaHDocID' => $rows->RiaHDocID]);
            if (!$riaH) {
                $globalDebug[$rows->RiaHDocID] = ["Missing RiaFrmHVLAB for {$rows->RiaHDocID}"];
                continue;
            }

            $hisReq = HisRequest::find()->where(['HN' => $riaH->PatHN, 'CustomerCode' => $riaH->CustID])->one();

            $filesData = [];
            $labNo = $hisReq->LabNo ?? '';
            $timestamp = date('dmYHis');
            $docIdParam = $rows['RiaHDocID'] ?? '';
            $debug = [];

            if (!empty($docIdParam)) {
                $dirUrl = 'https://report.prolab.co.th/pdflink/' . $docIdParam . '/';
                $possibleFiles = [];
                for ($j = 1; $j <= 20; $j++) {
                    $possibleFiles[] = $docIdParam . '_' . $j . '.pdf';
                }
                $possibleFiles[] = $docIdParam . '.pdf';
                $possibleFiles[] = 'report.pdf';
                $possibleFiles[] = 'result.pdf';

                foreach ($possibleFiles as $fileName) {
                    $fileUrl = $dirUrl . $fileName;

                    // HEAD check
                    $ch = curl_init($fileUrl);
                    curl_setopt($ch, CURLOPT_NOBODY, true);
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
                    curl_setopt($ch, CURLOPT_TIMEOUT, 5);
                    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
                    $head = curl_exec($ch);
                    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                    $curlErr = curl_errno($ch) ? curl_error($ch) : null;
                    curl_close($ch);

                    $debug[] = "Checking: {$fileName} -> HTTP {$httpCode}" . ($curlErr ? " (curlErr: {$curlErr})" : '');

                    if ($httpCode == 200) {
                        // GET content
                        $ch2 = curl_init($fileUrl);
                        curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
                        curl_setopt($ch2, CURLOPT_FOLLOWLOCATION, true);
                        curl_setopt($ch2, CURLOPT_TIMEOUT, 15);
                        curl_setopt($ch2, CURLOPT_SSL_VERIFYPEER, false);
                        $content = curl_exec($ch2);
                        $curlErr2 = curl_errno($ch2) ? curl_error($ch2) : null;
                        curl_close($ch2);

                        if ($content !== false && !empty($content)) {
                            $ext = pathinfo($fileName, PATHINFO_EXTENSION);
                            $newFileName = ($labNo ?: 'lab') . '_' . $timestamp . '.' . $ext;

                            $finfo = new finfo(FILEINFO_MIME_TYPE);
                            $mime = $finfo->buffer($content);

                            $filesData[] = [
                                'filename' => $newFileName,
                                'base64'   => base64_encode($content),
                                'size'     => strlen($content),
                                'mimetype' => $mime,
                            ];

                            $debug[] = "Success: Loaded {$fileName} (" . strlen($content) . " bytes)" . ($curlErr2 ? " (curlErr: {$curlErr2})" : '');
                        } else {
                            $debug[] = "Empty content for {$fileName}" . ($curlErr2 ? " (curlErr: {$curlErr2})" : '');
                        }
                    }
                }

                if (empty($filesData)) {
                    $debug[] = "No file found in {$dirUrl}";
                }
            } else {
                $debug[] = "docIdParam empty";
            }

            $globalDebug[$docIdParam ?: 'no_doc_id_' . uniqid()] = $debug;

            // ===== สร้าง TestItem =====
            $testItem = [
                'TestCode' => (string)($rows->TestCode ?? ''),
                'TestName' => (string)($rows->TestName ?? ''),
                'TestRemark' => '',
                'InformCriticalByCode' => '',
                'InformCriticalBy' => '',
                'InformCriticalTo' => '',
                'InformCriticalDateTime' => '',
                'CriticalFlag' => '',
                'ReportResultByCode' => '',
                'ReportResultBy' => (string)($rows->RiaLDUserNameEntry ?? ''),
                'ReportResultDateTime' => $this->dateTimeFormat($rows->RiaLDUserDateEntry ?? ''),
                'ApproveResultByCode' => '',
                'ApproveResultBy' => (string)($rows->RiaLDUserNameAppr ?? ''),
                'ApproveResultDateTime' => $this->dateTimeFormat($rows->RiaLDUserDateAppr ?? ''),
                'Filedata' => array_map(function ($f) {
                    return [
                        'FileName'   => $f['filename'],
                        'Filebase64' => $f['base64'],
                    ];
                }, $filesData),
                'ResultList' => [
                    [
                        'ResultCode' => (string)($rows->TestCode ?? ''),
                        'ResultName' => (string)($rows->TestName ?? ''),
                        'ResultValue' => (string)($rows->RiaLDRsltAnal ?? ''),
                        'ResultUnit' => (string)($rows->LabUnit ?? ''),
                        'ResultFlag' => '',
                        'ReferenceRange' => trim(($rows->LabNormal1 ?? '') . ' ' . ($rows->LabNormal2 ?? '')),
                        'ResultRemark' => '',
                    ]
                ],
            ];

            // ===== จัดกลุ่มตาม LabNo =====
            if (!isset($groupedByLabNo[$labNo])) {
                $groupedByLabNo[$labNo] = [
                    'LabNo' => $labNo,
                    'RequestRemark' => '',
                    'ResultStatus' => '',
                    'TestList' => []
                ];
            }
            $groupedByLabNo[$labNo]['TestList'][] = $testItem;
            $sendMapping[$rows->RiaHDocID] = $rows->RiaHDocID;
        }

        // ===== เตรียม payload (เลือก record แรกของ groupedByLabNo) =====
        $testList = $groupedByLabNo;
        $payload = count($testList) > 0 ? array_values($testList)[0] : null;

        // ===== ตรวจสอบ config =====
        $cfg = Yii::$app->params['external_api'] ?? null;
        if (!$cfg) {
            return [
                'error' => 'Config external_api not found',
                'sent_payload' => $testList,
                'file_debug' => $globalDebug
            ];
        }

        if (empty($cfg['receiveUrl'])) {
            return [
                'error' => 'receiveUrl not configured',
                'config' => $cfg,
                'sent_payload' => $testList,
                'file_debug' => $globalDebug
            ];
        }

        // ===== ขอ token =====
        $tokenError = null;
        $token = $this->getValidApiToken($cfg, $tokenError);

        if (!$token) {
            return [
                'error' => 'Cannot get API token',
                'token_error' => $tokenError,
                'sent_payload' => $testList,
                'file_debug' => $globalDebug
            ];
        }

        $url = $cfg['receiveUrl'];

        if (!$payload) {
            return [
                'error' => 'No test data to send',
                'sent_payload' => $testList,
                'file_debug' => $globalDebug
            ];
        }

        // ===== ส่ง payload โดยตรง (ไม่ห่อด้วย dataJson) =====
        $wrappedPayload = $payload;

        $debugInfo = [
            'url' => $url,
            'tokenUrl' => $cfg['tokenUrl'] ?? 'not set',
            'token_exists' => !empty($token),
            'token_length' => strlen($token ?? ''),
            'payload_count' => count($testList),
            'payload_size' => strlen(json_encode($wrappedPayload, JSON_UNESCAPED_UNICODE)),
        ];

        $response = $this->postJsonCurl($url, $wrappedPayload, [
            'Authorization' => "Bearer {$token}",
        ]);

        // รวม debug และ file debug
        $response['debug_info'] = $debugInfo;
        $response['file_debug'] = $globalDebug;
        $response['token_received'] = $token;
        if ($tokenError) {
            $response['token_warning'] = $tokenError;
        }

        // ===== ตรวจ response ตามสเป็ค (Status number, 0 = Success) =====
        $success = false;
        $decoded = null;

        if (!empty($response['response'])) {
            $decoded = json_decode($response['response'], true);

            if (is_array($decoded)) {
                // ตรวจ Status field (รองรับ 'Status' หรือ 'status')
                $statusVal = $decoded['Status'] ?? ($decoded['status'] ?? null);
                if ($statusVal !== null) {
                    if (is_numeric($statusVal)) {
                        $success = (intval($statusVal) === 0);
                    } else {
                        $s = strtolower(trim((string)$statusVal));
                        if ($s === '0' || $s === 'success' || $s === 'ok') {
                            $success = true;
                        }
                    }
                }

                // fallback: ถ้าไม่มี Status ให้ตรวจ Message
                if (!$success) {
                    $msg = strtolower(trim($decoded['Message'] ?? ($decoded['message'] ?? '')));
                    if ($msg !== '' && (strpos($msg, 'success') !== false || strpos($msg, 'successful') !== false)) {
                        $success = true;
                    }
                }
            }
        }

        Yii::info('External API decoded response: ' . var_export($decoded, true), __METHOD__);
        Yii::info('Determined success = ' . ($success ? 'true' : 'false') . '; http_code=' . ($response['http_code'] ?? ''), __METHOD__);

        // ===== ถ้า success ให้บันทึก LisResult (status = 1) =====
        if ($success) {
            foreach ($RiaLabD as $rows) {
                $riaH = RiaFrmHVLAB::findOne(['RiaHDocID' => $rows->RiaHDocID]);
                if (!$riaH) continue;
                $hisReq = HisRequest::find()->where(['HN' => $riaH->PatHN, 'CustomerCode' => $riaH->CustID])->one();
                if (!$hisReq) {
                    Yii::warning("No HisRequest for HN={$riaH->PatHN} Cust={$riaH->CustID} RiaHDocID={$rows->RiaHDocID}", __METHOD__);
                    continue;
                }

                $LisResult = LisResult::find()->where([
                    'lab_no' => $hisReq->LabNo,
                    'test_code' => $rows->LabID,
                    'cust_id' => $riaH->CustID,
                    'hn' => $riaH->PatHN
                ])->one();

                if (!$LisResult) {
                    $LisResult = new LisResult([
                        'lab_no' => $hisReq->LabNo,
                        'riah_doc_id' => $rows->RiaHDocID,
                        'riah_doc_date' => $rows->RiaHDocDate,
                        'test_code' => $rows->LabID,
                        'test_name' => $rows->LabName,
                        'cust_id' => $riaH->CustID,
                        'hn' => $riaH->PatHN,
                        'result_value' => $rows->RiaLDRsltAnal ?? '',
                        'result_unit' => $rows->LabUnit ?? '',
                        'reference_range' => trim(($rows->LabNormal1 ?? '') . ' ' . ($rows->LabNormal2 ?? '')),
                        'status' => 1,
                    ]);
                    if (!$LisResult->save(false)) {
                        Yii::error("Failed to save LisResult for lab_no={$hisReq->LabNo} test_code={$rows->LabID}", __METHOD__);
                    }
                } else {
                    $LisResult->status = 1;
                    if (!$LisResult->save(false)) {
                        Yii::error("Failed to update LisResult id={$LisResult->id}", __METHOD__);
                    }
                }
            }
        }

        return ['sent_payload' => $testList, 'response' => $response, 'api_decoded' => $decoded];
    }

    /** helper: แปลง datetime เป็น dd/mm/YYYY H:i:s */
    public function dateTimeFormat($value)
    {
        if (empty($value)) return '';
        try {
            $dt = new \DateTime($value);
            return $dt->format('d/m/Y H:i:s');
        } catch (\Throwable $e) {
            return '';
        }
    }

    /**
     * ขอ token จาก API (คืนค่า associative array แบบ {ok, token, expires_at, http_code, raw, error})
     */
    protected function getApiToken($cfg)
    {
        $tokenUrl = $cfg['tokenUrl'] ?? Yii::$app->params['external_api']['tokenUrl'] ?? null;
        $username = $cfg['username'] ?? Yii::$app->params['external_api']['username'] ?? null;
        $password = $cfg['password'] ?? Yii::$app->params['external_api']['password'] ?? null;

        $payload = ['username' => $username, 'password' => $password];

        $ch = curl_init($tokenUrl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Accept: application/json']);
        curl_setopt($ch, CURLOPT_TIMEOUT, 15);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

        $raw = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curlErr = curl_errno($ch) ? curl_error($ch) : null;
        curl_close($ch);

        $result = ['ok' => false, 'token' => null, 'expires_at' => null, 'http_code' => $httpCode, 'raw' => $raw, 'error' => null];

        if ($raw === false || $curlErr) {
            $result['error'] = 'cURL error: ' . ($curlErr ?? 'unknown');
            return $result;
        }

        $decoded = json_decode($raw, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            $result['error'] = 'Invalid JSON response from token endpoint';
            return $result;
        }

        if (!empty($decoded['access_token'])) {
            $result['ok'] = true;
            $result['token'] = $decoded['access_token'];
            $expiresIn = intval($decoded['expires_in'] ?? 3600);
            $result['expires_at'] = date('Y-m-d H:i:s', time() + $expiresIn);
        } elseif (!empty($decoded['token'])) {
            $result['ok'] = true;
            $result['token'] = $decoded['token'];
            $expiresIn = intval($decoded['expires_in'] ?? 3600);
            $result['expires_at'] = date('Y-m-d H:i:s', time() + $expiresIn);
        } else {
            $result['error'] = $decoded['error'] ?? ($decoded['message'] ?? 'No token in response');
        }

        return $result;
    }

    /**
     * ดึง token ที่ valid (คืน token string หรือ null และตั้ง $tokenError หากมีปัญหา)
     */
    protected function getValidApiToken($cfg, &$tokenError = null)
    {
        $apiName = $cfg['apiName'] ?? 'gems_api';
        $tokenModel = ApiToken::find()->where(['api_name' => $apiName])->one();
        $token = null;
        $nowTs = time();
        $refreshMargin = $cfg['refreshMargin'] ?? 300; // 5 นาที

        $needRequest = !$tokenModel || (strtotime($tokenModel->expires_at) <= ($nowTs + $refreshMargin));

        if ($needRequest) {
            $tokenResp = $this->getApiToken($cfg);

            if (empty($tokenResp) || empty($tokenResp['ok'])) {
                $tokenError = [
                    'message' => 'Failed to get token from API',
                    'tokenUrl' => $cfg['tokenUrl'] ?? null,
                    'error' => $tokenResp['error'] ?? 'Unknown error',
                    'http_code' => $tokenResp['http_code'] ?? 0,
                    'raw' => $tokenResp['raw'] ?? null,
                ];

                if ($tokenModel && !empty($tokenModel->token)) {
                    return $tokenModel->token; // fallback: ใช้ token เก่า
                }

                return null;
            }

            $token = $tokenResp['token'];
            $expiresAt = $tokenResp['expires_at'] ?? date('Y-m-d H:i:s', time() + 3600);

            if (!$tokenModel) {
                $tokenModel = new ApiToken();
                $tokenModel->api_name = $apiName;
            }
            $tokenModel->token = $token;
            $tokenModel->expires_at = $expiresAt;
            $tokenModel->save(false);
        } else {
            $token = $tokenModel->token;
        }

        return $token;
    }

    /** helper: ส่ง JSON ผ่าน cURL (คืนข้อมูล debug เต็ม) */
    protected function postJsonCurl($url, $payload, $headers = [])
    {
        $ch = curl_init($url);
        $jsonPayload = json_encode($payload, JSON_UNESCAPED_UNICODE);

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonPayload);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_TIMEOUT, 60);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

        $curlHeaders = ['Content-Type: application/json', 'Accept: application/json'];
        foreach ($headers as $k => $v) {
            if (is_int($k)) {
                $curlHeaders[] = $v;
            } else {
                $curlHeaders[] = "{$k}: {$v}";
            }
        }
        curl_setopt($ch, CURLOPT_HTTPHEADER, $curlHeaders);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curlError = curl_errno($ch) ? curl_error($ch) : null;
        $curlErrno = curl_errno($ch);
        curl_close($ch);

        return [
            'http_code' => $httpCode,
            'response' => $response,
            'curl_error' => $curlError,
            'curl_errno' => $curlErrno,
            'url' => $url,
            'payload_size' => strlen($jsonPayload),
        ];
    }
}