<?php

namespace App\Http\Services\Backend\DataManagement;

use App\Http\Services\ConstDef\GeneralConst;
use App\Models\Web\Activity;
use App\Models\Web\Receipt;
use App\Models\Web\Syslogact;

class ActivityManagementService
{
    // 相關私有 model 調用器宣告
    private $activityManagementDb;
    private $receiptManagementDb;
    private $syslogactManagementDb;
    
    public function __construct()
    {
        date_default_timezone_set("Asia/Taipei");
        // 建構 model 調用器
        $this->activityManagementDb = new Activity();
        $this->receiptManagementDb = new Receipt();
        $this->syslogactManagementDb = new Syslogact();
    }
    
    public function getActivitys(
        &$cnt = 0,
        $orderColumn,
        $orderDir,
        $start,
        $length,
        $searchValue
    )
    {
        $activity = $this->activityManagementDb
            ->select([
                'id',
                \DB::raw("CONCAT('<a href=\"activityManagement/edit/', id, '\">', activityName, '</a>') as activityName"),
                \DB::raw("CONCAT(reqTimeBegin, '<br>', reqTimeFinal) as reqTime"),
                'drawTime',
                \DB::raw("replace(drawNumbers, ',', '<br>') as drawNumbers"),
                \DB::raw("
                    (case
                        -- 現在時間小於開獎時間 (NOW是+8時區，UNIX_TIMESTAMP之後就變成+0時區)
                        when UNIX_TIMESTAMP(NOW()) < UNIX_TIMESTAMP(CONCAT(drawTime, ' 00:00:00'))
                        then '尚未到開獎時間'
                        -- 現在時間大於開獎時間
                        else (case isDraw
                            -- 決定顯示出來的開獎按鈕可不可以按
                            when '' then CONCAT('<a href=\"#\" onclick=\"confirmUser(''activityManagement/draw/', id, ''')\">點我開獎</a>')
                            else '已經開獎'
                        end)
                    end) as drawBtn
                "),
                \DB::raw("CONCAT(redeemTimeBegin, '<br>', redeemTimeFinal) as redeemTime"),
                \DB::raw("
                    (case
                        -- 現在時間小於驗證時間首日 (NOW是+8時區，UNIX_TIMESTAMP之後就變成+0時區)
                        when UNIX_TIMESTAMP(NOW()) < UNIX_TIMESTAMP(CONCAT(checkTimeBegin, ' 00:00:00'))
                        then '尚未到驗證時間'
                        -- 現在時間大於驗證時間首日
                        else (case isCheckBegin
                            -- 決定顯示出來的驗證按鈕可不可以按
                            when '' then CONCAT('<a href=\"#\" onclick=\"confirmUser(''activityManagement/check/', id, ''')\">點我啟動驗證流程</a>')
                            else '已啟動驗證流程'
                        end)
                    end) as checkBtn
                "),
                \DB::raw("CONCAT(checkTimeBegin, '<br>', checkTimeFinal) as checkTime"),
                \DB::raw("CONCAT(getTimeBegin, '<br>', getTimeFinal) as getTime"),
                \DB::raw("
                    (case
                        -- 現在時間小於領獎時間迄日 (NOW是+8時區，UNIX_TIMESTAMP之後就變成+0時區)
                        when UNIX_TIMESTAMP(NOW()) < UNIX_TIMESTAMP(CONCAT(getTimeFinal, ' 00:00:00'))
                        then '尚未到領獎結束時間'
                        -- 現在時間大於領獎時間迄日
                        else (case isGetFinal
                            -- 決定顯示出來的驗證按鈕可不可以按
                            when '' then CONCAT('<a href=\"#\" onclick=\"confirmUser(''activityManagement/get/', id, ''')\">點我關閉領獎活動</a>')
                            else '已關閉領獎活動'
                        end)
                    end) as getBtn
                "),
                'cdate',
                'mdate',
                \DB::raw("(select name from users where id=activity.oid) as oid"),
            ]);
        // 過濾搜尋條件
        // 取總筆數
        $cnt = $activity->count();
        // 排序
        $activity = $activity
            ->orderByRaw((int)$orderColumn . ' ' . $orderDir);
        // 彙整
        // 分頁
        $activity = $activity
            ->skip($start)->take($length);
        // 實際取資料
        $activity = $activity
            ->get()
            ->toArray();
        
        // 整理返回值並返回
        return $activity;
    }
    
    public function getActivityById($id)
    {
        // 取得參數
        // 調用資料庫(或者其他業務邏輯)
        $activity = $this->activityManagementDb->select([
            'id',
            'activityName',
            'reqTimeBegin',
            'reqTimeFinal',
            'drawTime',
            'drawNumbers',
            'redeemTimeBegin',
            'redeemTimeFinal',
            'checkTimeBegin',
            'checkTimeFinal',
            'getTimeBegin',
            'getTimeFinal',
            'cdate',
            'mdate',
            \DB::raw("(select name from users where id=activity.oid) as oid"),
        ])
            ->where('id', $id)
            ->first()
            ->toArray();
        
        // 整理返回值並返回
        return $activity;
    }
    
    public function insertActivity($activityName, $reqTimeBegin, $reqTimeFinal, $drawTime, $drawNumbers, $redeemTimeBegin, $redeemTimeFinal, $checkTimeBegin, $checkTimeFinal, $getTimeBegin, $getTimeFinal, $oid)
    {
        // 取得參數
        $data = [
            'activityName'    => $activityName,
            'reqTimeBegin'    => $reqTimeBegin,
            'reqTimeFinal'    => $reqTimeFinal,
            'drawTime'        => $drawTime,
            'drawNumbers'     => $drawNumbers,
            'redeemTimeBegin' => $redeemTimeBegin,
            'redeemTimeFinal' => $redeemTimeFinal,
            'checkTimeBegin'  => $checkTimeBegin,
            'checkTimeFinal'  => $checkTimeFinal,
            'getTimeBegin'    => $getTimeBegin,
            'getTimeFinal'    => $getTimeFinal,
            'cdate'           => date('Y-m-d H:i:s'),
            'mdate'           => date('Y-m-d H:i:s'),
            'oid'             => $oid,
        ];
        // 調用資料庫(或者其他業務邏輯)
        $this->activityManagementDb
            ->insert($data);
        $id = \DB::getPdo()->lastInsertId();
        // syslogact
        $this->syslogactManagementDb
            ->insert([
                'type'    => GeneralConst::LOG_ADMIN,
                'func'    => __FUNCTION__,
                'k'       => $oid,
                'memoIn'  => json_encode(['data' => $data], JSON_UNESCAPED_UNICODE),
                'memoOut' => json_encode(['id' => $id], JSON_UNESCAPED_UNICODE),
                'cdate'   => date("Y-m-d H:i:s"),
            ]);
        
        // 整理返回值並返回
        return $id;
    }
    
    public function modifyActivity($id, $activityName, $reqTimeBegin, $reqTimeFinal, $drawTime, $drawNumbers, $redeemTimeBegin, $redeemTimeFinal, $checkTimeBegin, $checkTimeFinal, $getTimeBegin, $getTimeFinal, $oid)
    {
        // 取得參數
        $data = [
            'activityName'    => $activityName,
            'reqTimeBegin'    => $reqTimeBegin,
            'reqTimeFinal'    => $reqTimeFinal,
            'drawTime'        => $drawTime,
            'drawNumbers'     => $drawNumbers,
            'redeemTimeBegin' => $redeemTimeBegin,
            'redeemTimeFinal' => $redeemTimeFinal,
            'checkTimeBegin'  => $checkTimeBegin,
            'checkTimeFinal'  => $checkTimeFinal,
            'getTimeBegin'    => $getTimeBegin,
            'getTimeFinal'    => $getTimeFinal,
            'mdate'           => date('Y-m-d H:i:s'),
            'oid'             => $oid,
        ];
        // 調用資料庫(或者其他業務邏輯)
        $res = $this->activityManagementDb
            ->where('id', $id)
            ->update($data);
        $rc = \DB::select("SELECT ROW_COUNT() AS rc;");
        $rc = $rc[0]->rc;
        // syslogact
        $this->syslogactManagementDb
            ->insert([
                'type'    => GeneralConst::LOG_ADMIN,
                'func'    => __FUNCTION__,
                'k'       => $oid,
                'memoIn'  => json_encode(['id' => $id, 'data' => $data], JSON_UNESCAPED_UNICODE),
                'memoOut' => json_encode(['rc' => $rc], JSON_UNESCAPED_UNICODE),
                'cdate'   => date("Y-m-d H:i:s"),
            ]);
        
        // 整理返回值並返回
        return $res;
    }
    
    public function draw($id, $oid)
    {
        // 取得該期獎號
        $drawNumbers = $this->activityManagementDb
            ->select(['drawNumbers'])
            ->where('id', $id)
            ->where('isDraw', '') // 尚未開獎
            ->where('isCheckBegin', '')
            ->where('isGetFinal', '')
            ->whereRaw("UNIX_TIMESTAMP(NOW()) >= UNIX_TIMESTAMP(CONCAT(drawTime, ' 00:00:00'))") // 開獎時間再次確認
            ->first()->toArray();
        $drawNumbers = explode(',', $drawNumbers['drawNumbers']);
        // 掃描[該期][狀態=1=未開獎]的訂單編號，並比對獎號更改狀態，應該是兩句 SQL 就夠了
        $receipts = $this->receiptManagementDb
            ->select([
                'id',
                \DB::raw("FROM_BASE64(AES_DECRYPT(UNHEX(tranOrderNo), \"" . env('KK') . "\")) as tranOrderNo"),
            ])
            ->where('aid', $id)   // 是指定活動的
            ->where('rStatus', GeneralConst::RSTATUS_INIT) // 是初始登錄完畢狀態的
            ->where('canGet', '') // 以防萬一連這個欄位也檢查
            ->get()->toArray();
        $draw_fail = [];
        $draw_done = [];
        foreach ($receipts as $r) {
            if (in_array(substr($r['tranOrderNo'], -3), $drawNumbers)) {
                $draw_done[] = $r['id'];
            } else {
                $draw_fail[] = $r['id'];
            }
        }
        $this->receiptManagementDb
            ->whereIn('id', $draw_fail)
            ->where('aid', $id)   // 是指定活動的
            ->where('rStatus', GeneralConst::RSTATUS_INIT) // 是初始登錄完畢狀態的
            ->where('canGet', '') // 以防萬一連這個欄位也檢查
            ->update([
                'rStatus' => GeneralConst::RSTATUS_DRAW_FAIL,
                'mdate'   => date('Y-m-d H:i:s'),
                'oid'     => $oid,
            ]);
        $this->receiptManagementDb
            ->whereIn('id', $draw_done)
            ->where('aid', $id)   // 是指定活動的
            ->where('rStatus', GeneralConst::RSTATUS_INIT) // 是初始登錄完畢狀態的
            ->where('canGet', '') // 以防萬一連這個欄位也檢查
            ->update([
                'rStatus' => GeneralConst::RSTATUS_DRAW_DONE,
                'mdate'   => date('Y-m-d H:i:s'),
                'oid'     => $oid,
            ]);
        // 更改開獎狀態位
        $this->activityManagementDb
            ->where('id', $id)
            ->where('isDraw', '')
            ->where('isCheckBegin', '')
            ->where('isGetFinal', '')
            ->whereRaw("UNIX_TIMESTAMP(NOW()) >= UNIX_TIMESTAMP(CONCAT(drawTime, ' 00:00:00'))") // 開獎時間再次確認
            ->update([
                'isDraw' => 'Y',
                'mdate'  => date('Y-m-d H:i:s'),
                'oid'    => $oid,
            ]);
        // syslogact
        $data = [
            'aid'         => $id,
            'drawNumbers' => $drawNumbers,
            'draw_fail'   => $draw_fail,
            'draw_done'   => $draw_done,
        ];
        $this->syslogactManagementDb
            ->insert([
                'type'    => GeneralConst::LOG_ADMIN,
                'func'    => __FUNCTION__,
                'k'       => $oid,
                'memoIn'  => json_encode(['data' => $data], JSON_UNESCAPED_UNICODE),
                'memoOut' => json_encode([], JSON_UNESCAPED_UNICODE),
                'cdate'   => date("Y-m-d H:i:s"),
            ]);
        
        return true;
    }
    
    public function check($id, $oid)
    {
        // 取得該期ID (有點像脫褲子放屁，但這是為了確認時間是否符合以及各項狀態位的管控)
        $chk = $this->activityManagementDb
            ->select(['id'])
            ->where('id', $id)
            ->where('isDraw', 'Y') // 已開獎
            ->where('isCheckBegin', '') // 未啟動驗證
            ->whereRaw("UNIX_TIMESTAMP(NOW()) >= UNIX_TIMESTAMP(CONCAT(checkTimeBegin, ' 00:00:00'))") // 驗證流程時間再次確認
            ->get();
        if (count($chk) == 0) return false; // 碰到這種情況按完鈕後不會有反應，且操作人也不知為何，就需要工程師介入
        // 取得該期所有狀態位為已中獎但未送出驗證的紀錄
        $receipts = $this->receiptManagementDb
            ->select([
                'id',
            ])
            ->where('aid', $id)   // 是指定活動的
            ->where('rStatus', GeneralConst::RSTATUS_DRAW_DONE) // 是已中獎但未送出驗證的紀錄的
            ->where('canGet', '') // 以防萬一連這個欄位也檢查
            ->get()->toArray();
        $draw_done_expired = [];
        foreach ($receipts as $r) $draw_done_expired[] = $r['id'];
        $this->receiptManagementDb
            ->whereIn('id', $draw_done_expired)
            ->where('aid', $id)   // 是指定活動的
            ->where('rStatus', GeneralConst::RSTATUS_DRAW_DONE) // 是已中獎但未送出驗證的紀錄的
            ->where('canGet', '') // 以防萬一連這個欄位也檢查
            ->update([
                'rStatus' => GeneralConst::RSTATUS_DRAW_DONE_EXPIRED,
                'mdate'   => date('Y-m-d H:i:s'),
                'oid'     => $oid,
            ]);
        // 更改驗證狀態位
        $this->activityManagementDb
            ->where('id', $id)
            ->where('isDraw', 'Y')
            ->where('isCheckBegin', '')
            ->whereRaw("UNIX_TIMESTAMP(NOW()) >= UNIX_TIMESTAMP(CONCAT(checkTimeBegin, ' 00:00:00'))") // 開獎時間再次確認
            ->update([
                'isCheckBegin' => 'Y',
                'mdate'        => date('Y-m-d H:i:s'),
                'oid'          => $oid,
            ]);
        // syslogact
        $data = [
            'aid'               => $id,
            'draw_done_expired' => $draw_done_expired,
        ];
        $this->syslogactManagementDb
            ->insert([
                'type'    => GeneralConst::LOG_ADMIN,
                'func'    => __FUNCTION__,
                'k'       => $oid,
                'memoIn'  => json_encode(['data' => $data], JSON_UNESCAPED_UNICODE),
                'memoOut' => json_encode([], JSON_UNESCAPED_UNICODE),
                'cdate'   => date("Y-m-d H:i:s"),
            ]);
        
        return true;
    }
    
    public function get($id, $oid)
    {
        // 取得該期ID (有點像脫褲子放屁，但這是為了確認時間是否符合以及各項狀態位的管控)
        $chk = $this->activityManagementDb
            ->select(['id'])
            ->where('id', $id)
            ->where('isDraw', 'Y') // 已開獎
            ->where('isCheckBegin', 'Y') // 已啟動驗證
            ->where('isGetFinal', '') // 未關閉活動
            ->whereRaw("UNIX_TIMESTAMP(NOW()) >= UNIX_TIMESTAMP(CONCAT(getTimeFinal, ' 00:00:00'))") // 領獎時間再次確認
            ->get();
        if (count($chk) == 0) return false; // 碰到這種情況按完鈕後不會有反應，且操作人也不知為何，就需要工程師介入
        // 取得該期所有狀態位為已中獎但未送出驗證的紀錄
        $receipts = $this->receiptManagementDb
            ->select([
                'id',
            ])
            ->where('aid', $id)   // 是指定活動的
            ->where('rStatus', GeneralConst::RSTATUS_DRAW_DONE_REDEEM_DONE) // 是已驗證通過但未領取的
            ->where('canGet', 'Y') // 以防萬一連這個欄位也檢查
            ->get()->toArray();
        $get_done_expired = [];
        foreach ($receipts as $r) $get_done_expired[] = $r['id'];
        $this->receiptManagementDb
            ->whereIn('id', $get_done_expired)
            ->where('aid', $id)   // 是指定活動的
            ->where('rStatus', GeneralConst::RSTATUS_DRAW_DONE_REDEEM_DONE) // 是已驗證通過但未領取的
            ->where('canGet', 'Y') // 以防萬一連這個欄位也檢查
            ->update([
                'rStatus' => GeneralConst::RSTATUS_DRAW_DONE_REDEEM_DONE_EXPIRED,
                'mdate'   => date('Y-m-d H:i:s'),
                'oid'     => $oid,
            ]);
        // 更改驗證狀態位
        $this->activityManagementDb
            ->where('id', $id)
            ->where('isDraw', 'Y')
            ->where('isCheckBegin', 'Y')
            ->where('isGetFinal', '')
            ->whereRaw("UNIX_TIMESTAMP(NOW()) >= UNIX_TIMESTAMP(CONCAT(getTimeFinal, ' 00:00:00'))") // 領獎時間再次確認
            ->update([
                'isGetFinal' => 'Y',
                'mdate'      => date('Y-m-d H:i:s'),
                'oid'        => $oid,
            ]);
        // syslogact
        $data = [
            'aid'                 => $id,
            'redeem_done_expired' => $get_done_expired,
        ];
        $this->syslogactManagementDb
            ->insert([
                'type'    => GeneralConst::LOG_ADMIN,
                'func'    => __FUNCTION__,
                'k'       => $oid,
                'memoIn'  => json_encode(['data' => $data], JSON_UNESCAPED_UNICODE),
                'memoOut' => json_encode([], JSON_UNESCAPED_UNICODE),
                'cdate'   => date("Y-m-d H:i:s"),
            ]);
        
        return true;
    }
    
}