<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\{ File };
use PhpZip\ZipFile;
use Throwable;

class ExtensionsController extends Controller
{
    public function index(Request $request)
    {
        $extensions = [];

        try
        {
            $client = new Client(['verify' => false, 'http_errors' => false, 'timeout' => 10, 'headers' => ['purchase_code' => env('PURCHASE_CODE')]]);

            $payload = [
                "json" => [
                    "item" => "valexa",
                ]
            ];

            $items_api_url = config('app.codemayer_api')."/items";
  
            $response = $client->get($items_api_url, $payload);

            if($response->getStatusCode() == 200)
            {
                $installed_exts = $this->getInstalledExtensions();

                $extensions     = json_decode($response->getBody()->getContents(), false)->items ?? [];

                foreach($extensions as &$extension)
                {
                    $extension->installed = 0;
                    $extension->installed_version = null;
                    $extension->purchased = 0;

                    $zip_file = base_path("extensions/{$extension->filename}.zip");
                    $key_file = base_path("extensions/{$extension->filename}.txt");

                    if(file_exists($zip_file) && file_exists($key_file))
                    {
                      $license  = file_get_contents($key_file);
                      $license  = str_replace(PHP_EOL, '', $license);
                      $license  = trim($license);
                      
                      $_client = new Client(['verify' => false, 'http_errors' => false, 'timeout' => 5]);

                      $_items_api_url = config('app.codemayer_api')."/items/validate_license?license={$license}";
                    
                      $response = $_client->get($_items_api_url);

                      if($response->getStatusCode() == 200)
                      {
                        $body = json_decode((string)$response->getBody());

                        $extension->purchased = $body->status ?? 0;

                        $setup = $this->getSetupFile($extension->filename);

                        if(is_object($setup))
                        {
                          $extension->installed = isset($installed_exts[$setup->name]);
                          $extension->installed_version = $extension->installed ? $installed_exts[$setup->name]['version'] : null;
                        }
                      }
                    }
                }
            }
        }
        catch(Throwable $e)
        {

        }

        return view("back.extensions", compact('extensions'));
    }



    public function install(Request $request)
    { 
        $message = null;
        $setup   = $this->getSetupFile($request->name);

        if(is_array($setup))
        {
            return back()->with($setup);
        }

        // Extracting extension
        $zip = new ZipFile;

        $zip->openFile(base_path("extensions/{$setup->name}.zip"));

        if($zip->count())
        {
          $zip->extractTo(base_path("extensions"));

          $zip->close();

          // Installing extension
          if(is_dir(base_path("extensions/{$setup->name}")))
          {
            $installed_exts = $this->getInstalledExtensions();

            $installed = in_array("{$setup->name}", $installed_exts);

            if($installed)
            {
              $this->uninstall($request);
            }

            foreach($setup->files as $file => $destination)
            {
                if(is_dir(base_path("extensions/{$setup->name}/{$file}")))
                {
                    File::copyDirectory(base_path("extensions/{$setup->name}/{$file}"), base_path("{$destination}/".basename($file)));
                }
                else
                {
                    File::copy(base_path("extensions/{$setup->name}/{$file}"), base_path("{$destination}/".basename($file)));
                }
            }

            $installed_exts[$setup->name] = $setup;

            $result = file_put_contents(base_path("extensions/installed_exts.json"), 
                                        json_encode($installed_exts, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES));

            $message =  $result 
                        ? __(":name has been installed.", ['name' => "{$setup->name} V{$setup->version}"]) 
                        : __("Failde to install :name extension.", ['name' => "{$setup->name} V{$setup->version}"]);

            if($result)
            {
              File::cleanDirectory(base_path("extensions/{$setup->name}"));
              File::deleteDirectory(base_path("extensions/{$setup->name}"));
            }
          }
        }

        return back()->with(['message' => $message]);
    }



    public function uninstall(Request $request)
    {
        $status         = false;
        $installed_exts = $this->getInstalledExtensions();
        $setup          = $installed_exts[$request->name] ?? null;

        if($setup)
        {
          foreach($setup['files'] as $file => $destination)
          {
              if(is_dir(base_path("extensions/{$setup['name']}/{$file}")))
              {
                  File::deleteDirectory(base_path("{$destination}/".basename($file)));
              }
              else
              {
                  File::delete(base_path("{$destination}/".basename($file)));
              }
          }

          unset($installed_exts[$request->name]);

          file_put_contents(base_path("extensions/installed_exts.json"), json_encode($installed_exts, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES));

          $status = true;
        }

        if($request->redirect)
        {
          return back()->with(['message' => $status ? __("The extension has been uninstalled successfuly.") : __("This extension is not installed yet.")]);
        }

        return $status;
    }



    private function getInstalledExtensions()
    {
        $installed_exts = [];

        if(file_exists(base_path("extensions/installed_exts.json")))
        {
          $installed_exts = json_decode(file_get_contents(base_path("extensions/installed_exts.json")), true) ?? [];
        }

        return $installed_exts;
    }



    private function getSetupFile($extension_name)
    {
        if(!file_exists(base_path("extensions/{$extension_name}.zip")))
        {
            return ['message' => __('Please upload the extension zip file to "/extensions/" directory of your website and try again.')];
        }

        $zip_file = base_path("extensions/{$extension_name}.zip");
        
        if(!$setup = @file_get_contents("zip://{$zip_file}#setup.json"))
        {
          $setup = @file_get_contents("zip://{$zip_file}#{$extension_name}/setup.json");
        }

        if(!$setup)
        {
          return ['message' => __('Unable to get setup.json file from the extension zip file.')];
        }

        if(!$setup = json_decode($setup))
        {
            return ['message' => __("setup.json file has malformatted content.")];
        }

        return $setup;
    }
}
