<?php

class AuthApi extends Api
{
    public $apiName = 'auth';

    public function __construct($requestUri, $encryption=true) {
        $this->requestWhitelist['createAction'] = 1;
        $this->requestWhitelist['indexAction'] = 1;
        parent::__construct($requestUri, $encryption);
    }
    
    public function indexAction()
    {
        error_log("AuthApi::indexAction()");
        $message = 'Unhandled exception';
        $headers = getallheaders();
        try {
            if (!isset($headers["x-session-id"]) || $headers["x-session-id"]=="") {
                throw new Exception('Invalid session ID');
            }
            $db = new Db();
            $session = Auth::getMemberSessionBySessionID($db->getConnect(), $headers["x-session-id"]);
            if (!is_array($session) || !array_key_exists('member_id',$session) || $session['member_id']<1) {
                throw new Exception('Session was not found');
            }
            return $this->response([
                "member_id" => $session['member_id'],
                "session" => $session['session'],
                "created" => $session['created'],
                "updated" => $session['updated']
            ], 200);
        } catch (Exception $e) {
            $message = $e->getMessage();
            error_log($message);
        }
        // Check session
        return $this->response(
            array(
                'error' => $message
            ), 404);
    }

    /**
     * Method GET
     * Get single record (by id)
     * http://DOMAIN/auth/1
     * @return string
     */
    public function viewAction()
    {
        //id must be the first parameter after /address/x
        $member_id = array_shift($this->requestUri);
        $headers = getallheaders();
        $message = 'Data not found';

        try {
            if(!$member_id || (int)$member_id<1) {
                throw new Exception("Invalid member ID");
            }
            $db = new Db();
            $member = Auth::getMemberById($db->getConnect(), (int)$member_id);
            if(!$member || !isset($member["id"])) {
                throw new Exception("Invalid member ID");
            }
            if (isset($headers["sessionid"]) && $headers["sessionid"]!="") {
                $session = Auth::getMemberSession($db->getConnect(), (int)$member_id, $headers["sessionid"]);
                if (!$session || !isset($session["id"])) {
                    throw new Exception("Invalid session ID");
                }
            }
            if (isset($headers["access_token"]) && $headers["access_token"]!="") {
                $device = Auth::verifyAccessToken($db->getConnect(), (int)$member_id, $headers["access_token"]);
                if (!$devices || !isset($device["id"])) {
                    throw new Exception("Invalid access token");
                }
                return $this->response($member, 200);
            }
            if (isset($headers["refresh_token"]) && $headers["refresh_token"]!="") {
                $device = Auth::verifyRefreshToken($db->getConnect(), (int)$member_id, $headers["refresh_token"]);
                if (!$devices || !isset($device["id"])) {
                    throw new Exception("Invalid refresh token");
                }
                // Get new tokens
                $device = self::generateTokens($db, $device["id"]);
                $member["refresh_token"] = $device["refresh_token"];
                $member["access_token"] = $device["access_token"];
                return $this->response($member, 200);
            }
            return $this->response($member, 200);
        } catch (Exception $e) {
            $message = $e->getMessage();
        }
        return $this->response(
            array(
                'error'=> $message
            ), 404);
    }

    public function createAction()
    {
        error_log("AuthApi::createAction()");
        $message = "Data not found";
        $sessionid = $this->requestParams["sessionid"] ?? "";
        $member_id = (int)($this->requestParams["member_id"] ?? "0");
        $cordova = $this->requestParams["cordova"] ?? "";
        $model = $this->requestParams["model"] ?? "";
        $platform = $this->requestParams["platform"] ?? "";
        $uuid = $this->requestParams["uuid"] ?? "";
        $version = $this->requestParams["version"] ?? "";
        $manufacturer = $this->requestParams["manufacturer"] ?? "";
        $is_virtual = $this->requestParams["is_virtual"] ?? "false";
        $player_id = $this->requestParams["player_id"] ?? "";
        $country = $this->requestParams["country"] ?? "SG";
        $access_token = $this->requestParams["access_token"] ?? "";
        $refresh_token = $this->requestParams["refresh_token"] ?? "";
        error_log("member_id=".$member_id);
        error_log("player_id=".$player_id);
        error_log("sessionid=".$sessionid);
        error_log("access_token=".$access_token);
        error_log("refresh_token=".$refresh_token);
        try {
            if ($member_id<1 || $sessionid=="") {
                throw new Exception('Invalid member and/or session ID');
            }
            $data = [
                'member_id' => $member_id,
                'sessionid' => $sessionid,
                'player_id' => $player_id,
                'cordova' => $cordova,
                'model' => $model,
                'platform' => $platform,
                'uuid' => $uuid,
                'version' => $version,
                'manufacturer' => $manufacturer,
                'is_virtual' => $is_virtual,
                'country' => $country,
                'access_token' =>  $access_token,
                'refresh_token' =>  $refresh_token             
            ];
            $db = new Db();
            $session = Auth::getMemberSession($db->getConnect(), $member_id, $sessionid);
            if ($session==NULL || !isset($session["id"])) {
                throw new Exception('Invalid member session ID');
            }
            $device = Auth::getMemberDevice($db->getConnect(), $data);
            if ($device==NULL || !isset($device["id"])) {
                $device = Push::saveMemberPlayerId($db->getConnect(), $data);
            }
            if ($device==NULL || !isset($device["id"])) {
                throw new Exception('Failed to create or load device record');
            }
            // Generate new access/refresh tokens
            $generator = new RandomStringGenerator();
            $tokenLength = 36;
            $access_token = $generator->generate($tokenLength);
            $refresh_token = $generator->generate($tokenLength);
            $device = Auth::saveTokens($db->getConnect(), $device["id"], $refresh_token, $access_token);
            if ($device==NULL || !isset($device["id"])) {
                throw new Exception('Failed to persist tokens');
            }
            return $this->response($device, 200);
        } catch (Exception $e) {
            $message = $e->getMessage();
        }
        return $this->response(
            array(
                "error" => $message
            ), 404);
    }

    public function updateAction()
    {
        return $this->response(
            array(
                "error" => "Update error"
            ), 400);
    }

    public function deleteAction()
    {
        return $this->response(
            array(
                "error" => "Delete error"
            ), 500);
    }

    public function generateTokens($db, $id) {
        // Generate new access/refresh tokens
        $generator = new RandomStringGenerator();
        $tokenLength = 36;
        $access_token = $generator->generate($tokenLength);
        $refresh_token = $generator->generate($tokenLength);
        $device = Auth::saveTokens($db->getConnect(), $id, $refresh_token, $access_token);
        if ($device==NULL || !isset($device["id"])) {
            throw new Exception('Failed to persist tokens');
        }
        return $device;
    }
}
