<?php

namespace App\Controllers;
use CodeIgniter\RESTful\ResourceController;
use CodeIgniter\Controller;
use OneLogin\Saml2\Auth;
use Config\SamlSettings;
use SimpleXMLElement;

class SamlController extends ResourceController
{
    protected $format = 'json';
    private $auth;
    private $settings;

    public function __construct()
    {
        
        helper('common_helper');
        helper('jwt_helper');
        $settings = new SamlSettings();

        $config = [
            'sp' => [
                'entityId' => $settings->spEntityId,
                'assertionConsumerService' => [
                    'url' => $settings->spAssertionConsumerServiceUrl,
                ],
                'singleLogoutService' => [
                    'url' => $settings->spSingleLogoutServiceUrl,
                ],
                'x509cert' => $settings->spCert,
                'privateKey' => $settings->spPrivateKey, 
            ],
            'idp' => [
                'entityId' => $settings->idpEntityId,
                'singleSignOnService' => [
                    'url' => $settings->idpSSOUrl,
                ],
                'singleLogoutService' => [
                    'url' => $settings->idpSLOUrl,
                ],
                'x509cert' => $settings->idpX509Cert,
            ],
            'security' => [
                'authnRequestsSigned' => true,
                'logoutRequestSigned' => true, 
                'wantAssertionsSigned' => true,
                'signMetadata' => true, // Ensure metadata is signed
            ],
        ];

        $this->auth = new Auth($config);
    }

    public function index()
    {
        return view('landingpage');
    }
   

    // Initiate the SSO (Single Sign-On) process
    public function login()
    {
        $this->auth->login();
    }

    // Handle the Assertion Consumer Service (ACS) endpoint
    public function acs()
    {
        try {
            $this->auth->processResponse();
           
            if ($this->auth->isAuthenticated()) {


                $samlUserdata = $this->auth->getAttributes();
                $userProfile['samlNameId'] = $this->auth->getNameId();
                $userProfile['samlNameIdFormat'] = $this->auth->getNameIdFormat();
                $userProfile['samlNameidNameQualifier'] = $this->auth->getNameIdNameQualifier();
                $userProfile['samlNameidSPNameQualifier'] = $this->auth->getNameIdSPNameQualifier();
                $userProfile['samlSessionIndex'] = $this->auth->getSessionIndex();
                $userProfile['displayName'] = $samlUserdata['http://schemas.microsoft.com/identity/claims/displayname'][0] ?? 'Unknown';
              
                $res = checkUserExist($userProfile['displayName'], $userProfile['samlNameId']);

                if($res['status'] == true)
                {             
                    $token = generateJWT($res['data']);

                    return $this->respond([ 'status' => 200,'message' => 'Login successful','token' => $token ]);

                }else{
                    return $this->respond([ 'status' => 401,'message' => 'Login Failed','data' => [] ]);
                }
              
            } else {
                return $this->respond([ 'status' => 401,'message' => 'Unauthorized','data' => [] ]);
            }
        } catch (\Exception $e) {
        
            return $this->respond([ 'status' => 500,'message' => $e,'data' => [] ]);
        }
    }

    // Handle the Single Logout (SLO) process
    public function slo()
    {
        // $this->auth->logout();
        //Check if the user is authenticated using SAML
        if ($this->auth->isAuthenticated()) {
            // Log out from the SAML session
            $this->auth->logout();
            return $this->respond([ 'status' => 200,'message' => 'Successfully log out','data' => [] ]);
        } else {
            // If user is not authenticated, redirect to login
            return redirect()->to('/login');
        }
    }

    // Handle the logout response
    public function sls()
    {
        try {
            $this->auth->processSLO();
            return redirect()->to('/login');
        } catch (\Exception $e) {
            return redirect()->to('/login');
        }
    }

    public function metadata()
    {
        try {
            // Set the content type to XML
            header('Content-Type: application/xml');
    
            // Get the settings from the OneLogin SAML Auth instance
            $settings = $this->auth->getSettings();
    
            // Generate SP metadata XML
            $metadata = $settings->getSPMetadata();
    
            // Check if there are any errors in the metadata generation
            $errors = $settings->validateMetadata($metadata);
            if (!empty($errors)) {
                // Handle validation errors
                throw new \Exception('Invalid SP metadata: ' . implode(', ', $errors));
            }
    
            // Output the metadata XML directly
            echo $metadata; 
    
        } catch (\Exception $e) {
            // Handle exceptions and display an appropriate error message
            echo "Error generating metadata: " . htmlspecialchars($e->getMessage());
        }
    }


    // Check if the user is authenticated
    public function check()
    {
        if ($this->auth->isAuthenticated()) {
            return json_encode($this->auth->getAttributes());
        } else {
            return json_encode(['status' => 'Not authenticated']);
        }
    }
}
