<?php

namespace App\Controllers;

use CodeIgniter\Controller;
use CodeIgniter\HTTP\CLIRequest;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Psr\Log\LoggerInterface;

/**
 * Class BaseController
 *
 * BaseController provides a convenient place for loading components
 * and performing functions that are needed by all your controllers.
 * Extend this class in any new controllers:
 *     class Home extends BaseController
 *
 * For security be sure to declare any new methods as protected or private.
 */
abstract class BaseController extends Controller
{
    /**
     * Instance of the main Request object.
     *
     * @var CLIRequest|IncomingRequest
     */
    protected $request;

    /**
     * An array of helpers to be loaded automatically upon
     * class instantiation. These helpers will be available
     * to all other controllers that extend BaseController.
     *
     * @var list<string>
     */
    protected $helpers = [];

    protected $db;
    /**
     * Be sure to declare properties for any property fetch you initialized.
     * The creation of dynamic property is deprecated in PHP 8.2.
     */
    // protected $session;

    /**
     * @return void
     */
    public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
    {
        // Do Not Edit This Line
        parent::initController($request, $response, $logger);

        // Preload any models, libraries, etc, here.
        $this->db = \Config\Database::connect();
        // E.g.: $this->session = service('session');
    }

    public function APIcall($method, $url, $data)
    {
        //  $curl = curl_init();
        $curl = curl_init($url);
        switch ($method) {
            case "GET":
                $params2 = '';
                foreach ($data as $key2 => $value2)
                    $params2 .= $key2 . '=' . $value2 . '&';

                $params2 = trim($params2, '&');
                $url = $url . '?' . $params2;// add param to URL
                log_message('critical', "API URL FINAL =>" . $url);
                //curl_setopt($curl, CURLOPT_FRESH_CONNECT, true);
                //curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
                //curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
                break;
            case "POST":
                curl_setopt($curl, CURLOPT_POST, 1);
                if ($data)
                    //  curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
                    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
                //  curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
                break;
            case "PUT":
                curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
                if ($data)
                    curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
                break;
        }

        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HTTPHEADER, array(
            'APIKEY: RegisteredAPIkey',
            'Content-Type: application/json',
        ));

        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
        $result = curl_exec($curl);

        if (!$result) {
            echo("Connection failure!");
        }
        curl_close($curl);
        return json_decode($result, true);
    }

    public function ansibleLogin(): string
    {
        $token = null;
        if (isset($_ENV['ANSIBLE_LOGIN_TOKEN']) && $_ENV['ANSIBLE_LOGIN_TOKEN'] != '') {
            log_message('critical', "***** ***** Provision TOKEN CONFIGURED :: " . $_ENV['ANSIBLE_LOGIN_TOKEN']);
            return $_ENV['ANSIBLE_LOGIN_TOKEN'];
        }

        try {
            // Code that might throw an exception
            $result = "Unhandled exception";
            $base_url = $_ENV['ANSIBLE_AUTOMATION_SERVER_LOCATION'];
            $cookies = tempnam('/tmp', 'cookie.txt');

            # 1. Login
//            $url = $base_url . "/api/auth/login";
            $url = $base_url . $_ENV['ANSIBLE_LOGIN_URL'];
            log_message('critical', "***** ***** Provision LOGIN URL:: " . $url);

            $ch = curl_init($url);
            # Setup request to send json via POST.
            $payload = json_encode(array("auth" => "admin", "password" => "may12002"));
            curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
            curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
            # Return response instead of printing.
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            # Fetch the headers, not the body content:
            //curl_setopt($ch, CURLOPT_HEADER, true);  // we want headers
            //curl_setopt($ch, CURLOPT_NOBODY, true);  // we don't need body
            # Cookie jar
            curl_setopt($ch, CURLOPT_COOKIEJAR, $cookies);
            curl_setopt($ch, CURLOPT_COOKIEFILE, $cookies);

            # Send request.
            $result = curl_exec($ch);
            $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $result = 'HTTP code: ' . $httpcode;

            curl_close($ch);

            if ($httpcode != "204") {
                log_message('critical', "***** ***** Provision LOGIN FAILED*********** :: " . $result);

            } else {
                log_message('critical', "***** ***** Provision LOGIN COMPLETED :: NOW TOKEN :: ");
//                # 2. Get token
                $url = $base_url . $_ENV['ANSIBLE_TOKEN_URL'];
                $ch = curl_init($url);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($ch, CURLOPT_COOKIEJAR, $cookies);
                curl_setopt($ch, CURLOPT_COOKIEFILE, $cookies);
                $result = curl_exec($ch);
                $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                curl_close($ch);

                $token = null;
                $arr = json_decode($result, true);
                foreach ($arr as $item) {
                    if ($item["expired"] === false) {
                        $token = $item["id"];
                        break;
                    }
                }
                $result = "Found token: $token";
                # Print response.
                log_message('critical', "***** ***** Provision LOGIN TOKEN :: " . $token);
            }

        } catch (\Exception  $e) {
            log_message('critical', "***** ***** Provision LOGIN FAILED :: " . $e->getMessage());
        }


        return $token;
    }


    public function ansibleProvision($ansibleToken, $params)
    {
//        log_message('critical', "***** ***** Provision CALL:: ansibleProvision() Token ".$ansibleToken);
//        log_message('critical', "***** ***** Provision CALL:: ansibleProvision() Token ". serialize( $params));
        try {
            $result = "Unhandled exception";
            $base_url = $_ENV['ANSIBLE_AUTOMATION_SERVER_LOCATION'];
            //$PROJECT_ID= 8;
            $PROJECT_ID = $_ENV['ANSIBLE_AUTOMATION_PROJECT_ID'];

//        $url = $base_url . "/api/project/$PROJECT_ID/tasks";
//        $url = $base_url . "/project/$PROJECT_ID/tasks";
            $url = $base_url . $_ENV['ANSIBLE_TASK_URL'] . $PROJECT_ID . "/tasks";
            log_message('critical', "***** ***** Provision CALL URL:: " . $url);

            $headers = [
                'Content-Type:application/json',
                'Accept: application/json',
                'Authorization: Bearer ' . $ansibleToken
            ];
            $ch = curl_init($url);
            $payload = json_encode($params);
            //  $payload = json_encode( array( "template_id"=> 1, "debug" => false, "dry_run" => false, "playbook" => "first-playbook.yml", "environment" => "{}" ) );
            curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            $res = curl_exec($ch);

            // 4. Check for errors during the execution
            if (curl_errno($ch)) {
                $error_message =  'cURL error: ' . curl_error($ch);
                log_message('critical', "***** ***** Provision LAUNCHED ERROR :: " . $error_message);
            }
            
            $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $result .= "\n" . 'Launch task HTTP code: ' . $httpcode;
            log_message('critical', "***** ***** Provision LAUNCHED :: ansibleProvision(httpcode) " . $result);

            curl_close($ch);
        } catch (\Exception  $e) {
            log_message('critical', "***** ***** Provision TASK CREATION FAILED :: " . $e->getMessage());
        }


        # 4. Get tasks
//        $url = $base_url . "/api/project/$PROJECT_ID/tasks";
//        $url = $base_url . "/project/$PROJECT_ID/tasks";
        $url = $base_url . $_ENV['ANSIBLE_TASK_URL'] . $PROJECT_ID . "/tasks";
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $res = curl_exec($ch);
        $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $result .= "\n" . 'Get tasks HTTP code: ' . $httpcode;

        curl_close($ch);
        log_message('critical', "***** ***** Provision :: ansibleProvision(httpcode) " . $httpcode);
        ob_start();
        var_dump($headers);
        var_dump($res);
        $result .= "\n" . ob_get_clean();

        return $httpcode;
    }

//    public function ansibleProvisionBAD($ansibleToken,$params){
//        log_message('critical', "***** ***** Provision CALL:: ansibleProvision() Token ".$ansibleToken);
//        log_message('critical', "***** ***** Provision CALL:: ansibleProvision() Token ". serialize( $params));
//
//        $result = "Unhandled exception";
//        $base_url = "http://172.16.4.90:3000";
//        $PROJECT_ID= 8;
//        $cookies = tempnam('/tmp','cookie.txt');
//
//        # 1. Login
//        $url = $base_url . "/api/project/$PROJECT_ID/tasks";
//        log_message('critical', "***** ***** ansibleProvision CALL::URL ". $url);
//        $ch = curl_init( $url );
//        # Setup request to send json via POST.
//        $payload = json_encode( $params );
//        $authorization = "Authorization: Bearer ".$ansibleToken; // Prepare the authorisation token
//        curl_setopt( $ch, CURLOPT_POSTFIELDS, $payload );
//        curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json',$authorization));
//        # Return response instead of printing.
//        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
//        # Fetch the headers, not the body content:
//
//        # Send request.
//        $result = curl_exec($ch);
//        $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
//        $result = 'HTTP code: ' . $httpcode;
//
//        curl_close($ch);
//
//        log_message('critical', "***** ***** Provision :: ansibleProvision($httpcode) ".$httpcode);
//
//        if ($httpcode != "204") {
//            return "Login failed! $result";
//        }
//
//        return 0;
//
//    }
}
