<?php
/* 各API 需有 token_verify() token驗證function ，因各API撈取API金鑰方式不同*/
class WebAPIForMenuPage extends base_class
{


    /**
     * Leo
     * 新增門市機器警報
     */
    public function Create_store_alarm($params)
    {
        //設定寫入資料
        //必填
        $s_cashier_id = (string) $params["cashier"];
        $n_store_id = (int) $params["store"];
        $s_create_time = (string) $params["create_at"];
        $n_alarm_code = (int) $params["code"];
        //非必填
        $s_alarm_note = (string) isset($params["note"]) ? $params["note"] : "";

        //當狀態碼為0 (正常)時 查詢該門市最後一筆警報是否為需要賦歸通知的警報
        /* $n_reset_notify = 1;
        if ($n_alarm_code == 0) {
            $sql = sprintf(
                "SELECT TOP 1
                            _sar.alarm_code,
                            _secl.reset_notify
                    FROM 	
                        [%s].[dbo].[store_alarm_report] AS _sar 
                        LEFT JOIN [%s].[dbo].[store_error_code_list] AS _secl ON _secl.error_code = _sar.alarm_code
                    WHERE
                        _sar.store_id = :store_id
                    ORDER BY _sar.store_alarm_id DESC
                    ",
                $this->database_alarm,
                $this->database_alarm
            );

            //準備執行sql
            $sth = $this->pdo_sql->prepare($sql);
            $sth->execute([
                "store_id" => $n_store_id,
            ]);
            $row = $sth->fetch(PDO::FETCH_ASSOC);
            //賦歸用判斷 當reset_notify = 1 時 賦歸需發送正常通知
            $n_reset_notify = $row["reset_notify"];
        }*/


        //先查詢門市資訊
        $sql = sprintf(
            "SELECT 
                    _s.store_id
                    ,_s.store_name
                    ,_s.store_state
                    ,_c.cashier_state
			FROM 	
				[%s].[dbo].[store] AS _s 
                LEFT JOIN [%s].[dbo].[cashier] AS _c ON _c.store_id = _s.store_id
			WHERE
            _s.store_id = :store_id AND
            _c.cashier_id = :cashier_id
			",
            $this->database_trend,
            $this->database_trend
        );

        //準備執行sql
        $sth = $this->pdo_sql->prepare($sql);
        $sth->execute([
            "store_id" => $n_store_id,
            "cashier_id" => $s_cashier_id
        ]);
        $row = $sth->fetch(PDO::FETCH_ASSOC);
        $s_store_name = $row["store_name"];
        //營運狀態 0:尚未營運 1:營運中
        $s_store_state = $row["store_state"];
        //機台最後狀態 0:正常 1:警報 2:異常
        $n_last_cashier_state = (int) $row["cashier_state"];

        //查詢錯誤碼資訊
        $sql = sprintf(
            "SELECT 
                    _secl.error_name
                    ,_secl.error_handle
                    ,_secl.notify_state
                    ,_secl.stop_type
                    ,_secl.timely_state
			FROM 	
				[%s].[dbo].[store_error_code_list] AS _secl 
			WHERE
                _secl.error_code = :error_code
			",
            $this->database_alarm
        );
        //準備執行sql
        $sth = $this->pdo_sql->prepare($sql);
        $sth->execute([
            "error_code" => $n_alarm_code
        ]);
        $row = $sth->fetch(PDO::FETCH_ASSOC);
        $s_alarm_name = $row["error_name"];
        $s_alarm_handle = $row["error_handle"];
        //判斷是否通知notify
        $n_notify_state = $row["notify_state"];
        //判斷是否停機 0:不停機 1:停機 ，根據停機與否來更新cashier_state
        $n_stop_type = $row["stop_type"];
        //判斷是否及時發送警報 0:不及時 1:及時
        $n_timely_state = $row["timely_state"];
        //cashier_state 當stop_type為0 表示不停機 那此異常訊息為警報類(表示對於現場實際用戶操作影響不大), cashier_state 帶入1
        //當stop_type為1 表示停機 那此異常訊息為異常類(表示現場實際用戶已無法完成取貨操作), cashier_state 帶入2
        //cashier_state 0:正常 1:警報 2:異常 3:未上線

        $n_cashier_state = $n_stop_type == 1 ? 2 : 1;
        //假設警報code為零 則代表門市已復歸為正常狀態 需另外判斷該門市當前狀態為何，如果原先狀態為異常，則賦歸時的正常警報要送line通知
        if ($n_alarm_code == 0) {
            $n_cashier_state = 0;
            // if ($n_last_cashier_state != 0) {
            //     $n_notify_state = 1;
            // }
        }


        //開始 beginTransaction
        $this->pdo_sql->beginTransaction();

        $a_insert_arr = [
            "cashier_id" => $s_cashier_id,
            "store_id" => $n_store_id,
            "create_at" => $s_create_time,
            "alarm_code" => $n_alarm_code,
            "alarm_name" => $s_alarm_name,
            "alarm_note" => $s_alarm_note,
            "alarm_handle" => $s_alarm_handle,
            "alarm_stop" => $n_stop_type,
            "is_sent_notify" => $n_timely_state == 1 ? 1 : 0
        ];
        //拼接sql字串
        $sql = sprintf(
            "INSERT INTO [%s].[dbo].[store_alarm_report](
                cashier_id,
                store_id,
                create_at,
                alarm_code,
                alarm_name,
                alarm_note,
                alarm_handle,
                alarm_stop,
                is_sent_notify
            )
            VALUES
            (
                :cashier_id,
                :store_id,
                :create_at,
                :alarm_code,
                :alarm_name,
                :alarm_note,
                :alarm_handle,
                :alarm_stop,
                :is_sent_notify
            )
			",
            $this->database_alarm
        );
        //準備執行sql
        $sth = $this->pdo_sql->prepare($sql);
        $sth->execute($a_insert_arr);

        //更新 cashier 表
        $a_update_arr = [
            "cashier_id" => $s_cashier_id,
            "store_id" => $n_store_id,
            "cashier_state" => $n_cashier_state,
        ];
        //拼接sql字串
        $sql = sprintf(
            "UPDATE [%s].[dbo].[cashier]
            SET
                cashier_state = :cashier_state
            WHERE
                cashier_id = :cashier_id AND 
                store_id = :store_id           
			",
            $this->database_trend
        );
        //準備執行sql
        $sth = $this->pdo_sql->prepare($sql);
        $sth->execute($a_update_arr);

        //結束 Transaction 執行寫入
        $this->pdo_sql->commit();

        //準備通知line notify 僅通知營運中的門市
        if (
            $n_timely_state == 1 && //當異常警報類型為及時發送
            $n_notify_state == 1 && // 當異常警報類行為需要發送line
            $s_store_state == 1 // 當異常警報門市為營運中時
        ) {
            $a_notify_data = [
                "門市" => $s_store_name,
                "時間" => $s_create_time,
                "異常代碼" => $n_alarm_code,
                "異常狀況" => $s_alarm_name,
                "對應動作" => $s_alarm_handle,
                "備註" => $s_alarm_note,
            ];
            $this->line_notify($a_notify_data);
        }


        return "OK";
    }
    /**
     * Leo
     * api 驗證
     */
    public function api_verify($token, $params)
    {
        //門市編號
        $n_store_id = (int) $params["store"];
        if ($n_store_id == 0) { //門市編號為空
            throw new Exception("store 欄位不可為空", 91000);
        } else {    //檢查門市是否存在
            $sql = sprintf(
                "SELECT 
                        _s.store_id
                FROM 	
                    [%s].[dbo].[store] AS _s 
                WHERE
                    _s.store_id = :store_id ",
                $this->database_trend
            );
            //準備執行sql
            $sth = $this->pdo_sql->prepare($sql);
            $sth->execute([
                "store_id" => $n_store_id
            ]);
            $row = $sth->fetch(PDO::FETCH_ASSOC);
            if (empty($row)) {
                throw new Exception("store 異常", 91000);
            }
        }
        //機台序號
        $s_cashier_id = (string) $params["cashier"];
        if ($s_cashier_id == "") { //機台編號為空
            throw new Exception("cashier 欄位不可為空", 91000);
        } else { //檢查機台是否存在
            $sql = sprintf(
                "SELECT 
                        _c.cashier_id
                FROM 	
                    [%s].[dbo].[cashier] AS _c
                WHERE
                    _c.cashier_id = :cashier_id ",
                $this->database_trend
            );
            //準備執行sql
            $sth = $this->pdo_sql->prepare($sql);
            $sth->execute([
                "cashier_id" => $s_cashier_id
            ]);
            $row = $sth->fetch(PDO::FETCH_ASSOC);
            if (empty($row)) {
                throw new Exception("cashier error", 91000);
            }
        }
        //時間戳(單位秒)
        $s_send_at = (string) $params["send_at"];
        if ($s_send_at == "") { //時間戳為空
            throw new Exception("send_at 欄位不可為空", 91000);
        } else if ($this->check_timestamp_format($s_send_at) != true) {
            throw new Exception("send_at format error", 91000);
        }
        //Token
        if (trim($token) == "") { //Token為空
            throw new Exception("token 欄位不可為空", 91000);
        }
        //異常Code
        $n_alarm_code = (int) $params["code"];
        if (!isset($params["code"])) { // 異常Code為空
            throw new Exception("code 欄位不可為空", 91000);
        } else { //檢查異常Code是否存在
            $sql = sprintf(
                "SELECT 
                        _secl.error_code
                FROM 	
                    [%s].[dbo].[store_error_code_list] AS _secl 
                WHERE
                    _secl.error_code = :error_code ",
                $this->database_alarm
            );
            //準備執行sql
            $sth = $this->pdo_sql->prepare($sql);
            $sth->execute([
                "error_code" => $n_alarm_code
            ]);
            $row = $sth->fetch(PDO::FETCH_ASSOC);
            if (empty($row)) {
                throw new Exception("code does not exist", 91000);
            }
        }
        //異常create_at
        $s_create_at = (string) $params["create_at"];
        if ($s_create_at == "") { // 異常create_at為空
            throw new Exception("create_at 欄位不可為空", 91000);
        } else if ($this->check_date_format($s_create_at) != true) { //時間格式不正確
            throw new Exception("create_at 時間格式不正確", 91000);
        }




        //依據資料查詢門市API金鑰來進行Token驗證
        $sql = sprintf(
            "SELECT 
                    _s.store_api_key,
                    _c.cashier_id
            FROM 	
                 [%s].[dbo].[cashier] AS _c
                 LEFT JOIN [%s].[dbo].[store] AS _s ON _s.store_id = _c.store_id
            WHERE
                _c.store_id = :store_id AND
                _c.cashier_id = :cashier_id",
            $this->database_trend,
            $this->database_trend
        );
        //準備執行sql
        $sth = $this->pdo_sql->prepare($sql);
        $sth->execute([
            "store_id" => $n_store_id,
            "cashier_id" => $s_cashier_id
        ]);
        $row = $sth->fetch(PDO::FETCH_ASSOC);
        if (!empty($row)) {
            $s_api_key = $row["store_api_key"];
            if ($this->shopee_api_token_verify($token, $s_api_key, $s_send_at) != true) {
                throw new Exception("Token Verification Failed", 91001);
            }
        } else {
            //查詢不到該門市該機台
            throw new Exception("store and cashier not binding", 91000);
        }
        //更新最後連線時間
        $this->cashier_connect_time_update($n_store_id, $s_cashier_id, $s_send_at);
    }
}
