<?php
App::uses('Component', 'Controller');
App::uses('CakeEmail', 'Network/Email');
require_once(APP . 'Controller' . DS . 'Traits' . DS . 'ApiCallTrait.php');
use Google\Auth\Credentials\ServiceAccountCredentials;
class NotificationComponent extends Component
{
    use ApiCallTrait;
    /**
     * @var AppModel|bool|mixed|Model|object|string|null
     */
    private $PushToken;
    public function initialize(Controller $controller)
    {
        $this->PushToken = ClassRegistry::init('PushToken');
    }
    public function sendEmail($data) {
        $default = array(
            'host' => Configure::read('expensecount.email.smtp.host'),
            'port' => 587,
            'auth' => 'plain',
            'username' => Configure::read('expensecount.email.smtp.username'),
            'password' => Configure::read('expensecount.email.smtp.password'),
            'tsl' => false,
            'transport' => 'Smtp',
            'from' => array(Configure::read('expensecount.email.smtp.from') => 'ExpenseCount'),
            'returnPath' => Configure::read('expensecount.email.smtp.from'),
            'layout' => false,
            'emailFormat' => 'html',
            'charset' => 'utf-8',
            'headerCharset' => 'utf-8',
        );

        try {
            $Email = new CakeEmail($default);
            $Email->to($data["email_to"]);
            $Email->emailFormat('html');
            $Email->template($data["template"], null)->viewVars(array('data' => $data));
            $Email->subject($data["subject"]);
            $Email->replyTo($data["email_from"]);
            $Email->from(array(Configure::read('expensecount.email.smtp.from') => "ExpenseCount.com"));
            $Email->delivery = 'Smtp';
            return $Email->send();
        }catch (Exception $e) {
            CakeLog::write(LOG_ERR, 'Email sending failed: ' . $e->getMessage());
            return $e->getMessage();
        }
    }


    private function getAccessToken()
    {
        $cacheFile = TMP . 'fcm_token.cache';

        if (file_exists($cacheFile)) {
            $cached = json_decode(file_get_contents($cacheFile), true);
            if (!empty($cached['token']) && $cached['expires_at'] > time()) {
                return $cached['token'];
            }
        }

        $scopes = ['https://www.googleapis.com/auth/firebase.messaging'];

        $credentials = new ServiceAccountCredentials(
            $scopes,
            json_decode(file_get_contents(FIREBASE_SECRET), true)
        );

        $token = $credentials->fetchAuthToken();

        if (!isset($token['access_token'])) {
            throw new \Exception('Unable to get access token');
        }

        // Google tokens expire in 3600s; cache for 55 minutes to stay safely within that.
        file_put_contents($cacheFile, json_encode([
            'token'      => $token['access_token'],
            'expires_at' => time() + 3300,
        ]));

        return $token['access_token'];
    }

    public function sendPushNotification($tokens, $message, $async = false)
    {
        $projectId = FIREBASE_PROJECT_ID;
        if (empty($projectId)) {
            CakeLog::write(LOG_ERR, 'Push notification: Firebase project_id not configured');
            return ['error' => 'Firebase project_id not configured'];
        }
        $url = "https://fcm.googleapis.com/v1/projects/{$projectId}/messages:send";

        try {
            $accessToken = $this->getAccessToken();
        } catch (\Exception $e) {
            CakeLog::write(LOG_ERR, 'Push notification: Failed to get access token: ' . $e->getMessage());
            return ['error' => 'Failed to get access token: ' . $e->getMessage()];
        }

        $responses = [];

        foreach ($tokens as $key => $token) {
            $payload = [
                "message" => [
                    "token" => $token['token'],
                    "data" => $message,
                    "apns" => [
                        "payload" => [
                            "aps" => [
                                "alert" => [
                                    "title" => $message['title'],
                                    "body"  => $message['body']
                                ],
                                "sound" => "default",
                                "badge" => 1,
                                "mutable-content" => 1,
                                "content-available" => 1
                            ]
                        ]
                    ]
                ]
            ];
            $apiResponse = $this->fireAndForget($url, $payload, $accessToken);
            $responses[] = ['request' => [$token['user_id'], $token['device_id']], 'response' => $apiResponse];
        }

        return $responses;
    }

    public function send($users,$message){

        $tokens = array();
        if(!empty($users)){
            $filter = array('status' => 1,'user_id' => $users);
            $db_token = $this->PushToken->getToken($filter);

            if(!empty($db_token)) {
                foreach ($db_token as $token) {
                    $tokens[] = ['user_id'=>$token['PushToken']['user_id'],
                        'device_id'=>$token['PushToken']['device_id'],
                        'token'=> $token['PushToken']['push_token']];
                }
            }
            if(!empty($tokens)) {

                $response = $this->sendPushNotification($tokens, $message, true);

            }else{
                $response["status"] = "-99";
                $response["status_desc"] = "Push Token Not Found!";
                $response["input"] = $users;
            }

        }else{
            $response["status"] = "-99";
            $response["status_desc"] = "User Not Found!";
            $response["input"] = $users;
        }
        return $response;
    }

}
