#!/usr/bin/perl

#                                      Copyright 2025 WebPros International, LLC
#                                                           All rights reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited.

package Cpanel::Server::Handlers::CometWebProsOAuthCallback;

use cPstrict;

=head1 NAME

Cpanel::Server::Handlers::CometWebProsOAuthCallback - Handle WebPros OAuth callbacks for Comet plugin

=head1 DESCRIPTION

This handler serves a JavaScript interstitial page for Comet WebPros OAuth callbacks.
It bypasses normal session requirements and CSRF checks since it's a public OAuth callback.

=cut

use parent 'Cpanel::Server::Handler';

sub handler {
    my ($self) = @_;

    my $server_obj = $self->get_server_obj();
    my $document   = $server_obj->request()->get_document();

    # Only handle /comet_webpros_callback
    return unless $document =~ m{^\.?/comet_webpros_callback$};

    # Serve the JavaScript interstitial page
    my $html   = _generate_callback_page();
    my $socket = $server_obj->connection()->get_socket();

    # Send HTTP response directly to socket
    my $content_length = length($html);
    print {$socket} "HTTP/1.1 200 OK\r\n";
    print {$socket} "Content-Type: text/html; charset=utf-8\r\n";
    print {$socket} "Content-Length: $content_length\r\n";
    print {$socket} "Cache-Control: no-cache, no-store, must-revalidate\r\n";
    print {$socket} "Pragma: no-cache\r\n";
    print {$socket} "\r\n";
    print {$socket} $html;

    # Tell cpsrvd we've sent headers
    $server_obj->sent_headers_to_socket();

    return 1;
}

sub _generate_callback_page {
    return <<'HTML';
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebPros Authentication - Processing...</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            margin: 0;
            background: #f5f5f5;
        }
        .processing {
            text-align: center;
            background: white;
            padding: 2rem;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        .spinner {
            border: 4px solid #f3f3f3;
            border-top: 4px solid #3498db;
            border-radius: 50%;
            width: 40px;
            height: 40px;
            animation: spin 1s linear infinite;
            margin: 0 auto 1rem;
        }
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
        .message {
            color: #666;
            margin-top: 1rem;
        }
        .error {
            color: #d32f2f;
        }
    </style>
</head>
<body>
    <div class="processing">
        <div class="spinner"></div>
        <h2>Processing Authentication...</h2>
        <p class="message" id="status">Please wait while we complete your authentication.</p>
    </div>

    <script>
        (function() {
            const statusEl = document.getElementById('status');
            
            // Extract code and state from URL parameters
            const urlParams = new URLSearchParams(window.location.search);
            const code = urlParams.get('code');
            const state = urlParams.get('state');
            
            if (code && window.opener) {
                try {
                    // Send the authorization code back to the parent window
                    window.opener.postMessage({
                        type: 'webpros_auth_callback',
                        code: code,
                        state: state
                    }, window.location.origin);
                    
                    statusEl.textContent = 'Authentication successful! Closing window...';
                    
                    // Close this popup after a short delay
                    setTimeout(function() {
                        window.close();
                    }, 1000);
                } catch (error) {
                    statusEl.className = 'message error';
                    statusEl.textContent = 'Error communicating with parent window. Please close this window and try again.';
                    console.error('postMessage error:', error);
                }
            } else if (!code) {
                statusEl.className = 'message error';
                statusEl.textContent = 'No authorization code received. Please close this window and try again.';
            } else if (!window.opener) {
                statusEl.className = 'message error';
                statusEl.textContent = 'This page must be opened from the authentication dialog. Please close this window.';
            }
        })();
    </script>
</body>
</html>
HTML
}

1;
