<?php

use Kreait\Firebase\Factory;
use Kreait\Firebase\ServiceAccount;

trait ImageUploadTrait
{

    protected $firebase;

    private function getFirebaseInstance()
    {
        // $jsonfilePath = APP . DS . 'Config' . DS . FIREBASE_SECRET;
        $jsonfilePath = FIREBASE_SECRET;
        $serviceAccount = ServiceAccount::fromJsonFile($jsonfilePath);
        $this->firebase = (new Factory)->withServiceAccount($serviceAccount)->create();
    }

    public function uploadBase64Image($base64Image, $storagePath)
    {

        try {

            $this->getFirebaseInstance();

            $imageData = base64_decode($base64Image);
            $storage = $this->firebase->getStorage();
            $bucket = $storage->getBucket();

            $object = $bucket->upload($imageData, [
                'name' => $storagePath
            ]);

            if ($object) {
                $imageUrl = "https://storage.googleapis.com/{$bucket->name()}/{$storagePath}";
                return ['status' => true, 'message' => 'Uploaded', 'url' => $imageUrl];
            } else {
                return ['status' => false, 'message' => 'Upload failed.'];
            }
        } catch (\Exception $e) {
            return ['status' => false, 'message' => 'Error uploading image: ' . $e->getMessage()];
        }
    }

    public function deleteFolder($storagePath)
    {

        try {

            $this->getFirebaseInstance();

            $storage = $this->firebase->getStorage();
            $bucket = $storage->getBucket();
            $objects = $bucket->object($storagePath);

            $objects = $bucket->objects([
                'prefix' => $storagePath
            ]);

            $filesDeleted = 0;

            foreach ($objects as $object) {
                $object->delete();
                $filesDeleted++;
            }

            if ($filesDeleted > 0) {
                return ['status' => true, 'message' => "Deleted folder :{$storagePath}"];
            } else {
                return ['status' => false, 'message' => "No files found in the folder."];
            }
        } catch (Exception $e) {
            return ['status' => false, 'message' => $e->getMessage()];
        }
    }

    public function singleImageDelete($storagePath)
    {
        try {

            $this->getFirebaseInstance();

            $storage = $this->firebase->getStorage();
            $bucket = $storage->getBucket();
            $object = $bucket->object($storagePath);
            $filesDeleted = 0;

            if ($object->exists()) {
                $object->delete();
                $filesDeleted++;
            }

            if ($filesDeleted > 0) {
                return ['status' => true, 'message' => "File deleted."];
            } else {
                return ['status' => false, 'message' => "No file found."];
            }
        } catch (Exception $e) {

            return ['status' => false, 'message' => $e->getMessage()];
        }
    }

    public function downloadImage($basePath, $expire_time='+2 days',$save_path=null)
    {
        try {

            $this->getFirebaseInstance();

            $storage = $this->firebase->getStorage();
            $bucket = $storage->getBucket();

            // Get object from Firebase Storage
            $zipPath  = $basePath . "receipts_" . time() . ".zip";
            $objects = $bucket->objects([
                'prefix' => $basePath
            ]);

            $files = [];

            foreach ($objects as $object) {

                $name = $object->name();

                // skip "folder itself"
                if (substr($name, -1) === '/') {
                    continue;
                }

                $files[] = $object;
            }

            $zip = new ZipArchive();
            $zipFile = TMP . "receipts_" . time() . ".zip";

            $zip->open($zipFile, ZipArchive::CREATE);

            foreach ($files as $file) {

                $fullPath = $file->name();

                if (strpos($fullPath, $basePath) === 0) {
                    $relativePath = substr($fullPath, strlen($basePath));
                } else {
                    $relativePath = basename($fullPath);
                }

                $content = $file->downloadAsString();

                $zip->addFromString($relativePath, $content);
            }

            $zip->close();
            $zipObject = $bucket->upload(
                file_get_contents($zipFile),
                [
                    'name' => $save_path
                ]
            );
            if (file_exists($zipFile)) {
                unlink($zipFile);
            }
            $expiresAt = new DateTime($expire_time);
            $downloadUrl = $zipObject->signedUrl($expiresAt);

            return [
                'status' => true,
                'message' => 'Downloaded successfully.',
                'download_url' => $downloadUrl,
                'file_path' => $zipPath,
                'expires_at' => $expiresAt->format('Y-m-d H:i:s')

            ];

        } catch (\Exception $e) {

            return [
                'status' => false,
                'message' => 'Error downloading image: ' . $e->getMessage()
            ];
        }
    }

    public function downloadLink($downloadPath, $expire_time='+2 days')
    {
        try {

            $this->getFirebaseInstance();

            $storage = $this->firebase->getStorage();
            $bucket = $storage->getBucket();

            $object = $bucket->object($downloadPath);

            $expiresAt = new DateTime($expire_time);
            $downloadUrl = $object->signedUrl($expiresAt,[
                'version' => 'v4'
            ]);

            return  $downloadUrl;

        } catch (\Exception $e) {

            return [
                'status' => false,
                'message' => 'Error downloading image: ' . $e->getMessage()
            ];
        }
    }
}
