<?php

declare(strict_types=1);

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Slack notification utility for trainer registrations and ticket purchases.
 *
 * Uses Slack Incoming Webhooks with Block Kit rich formatting.
 * All sends are non-blocking (fire-and-forget) so Slack failures
 * never affect registration or checkout flows.
 */
class HVAC_Slack_Notifications {

    /** @var bool Prevents duplicate hook registration */
    private static bool $initialized = false;

    /**
     * Register hooks. Called once from HVAC_Plugin::initializeSecondaryComponents().
     */
    public static function init(): void {
        if (self::$initialized) {
            return;
        }
        self::$initialized = true;

        // Ticket purchase: fires on any post status transition
        add_action('transition_post_status', [__CLASS__, 'on_order_status_change'], 10, 3);

        // Event published by admin (any tribe_events post transitioning to publish)
        add_action('transition_post_status', [__CLASS__, 'on_event_status_change'], 10, 3);

        // Event submitted by trainer via TEC Community Events form
        add_action('hvac_tec_event_saved', [__CLASS__, 'notify_event_submitted'], 10, 1);

        // AJAX: test webhook from settings page
        add_action('wp_ajax_hvac_test_slack_webhook', [__CLASS__, 'send_test_notification']);
    }

    /**
     * Send a message to Slack via Incoming Webhook.
     *
     * @param string $text   Plain-text fallback (required by Slack).
     * @param array  $blocks Block Kit blocks for rich layout.
     * @param bool   $blocking Whether to wait for the response.
     * @return bool|null True on success, false on failure, null if disabled.
     */
    private static function send(string $text, array $blocks, bool $blocking = false): ?bool {
        $webhook_url = get_option('hvac_slack_webhook_url', '');

        if (empty($webhook_url)) {
            return null; // Disabled — no webhook configured
        }

        // Validate URL: must be https://hooks.slack.com/services/...
        $scheme = parse_url($webhook_url, PHP_URL_SCHEME);
        $host   = parse_url($webhook_url, PHP_URL_HOST);
        $path   = parse_url($webhook_url, PHP_URL_PATH) ?: '';
        if ($scheme !== 'https' || $host !== 'hooks.slack.com' || !str_starts_with($path, '/services/')) {
            error_log('[HVAC Slack] Rejected webhook URL: ' . $webhook_url);
            return false;
        }

        $payload = wp_json_encode([
            'text'   => $text,
            'blocks' => $blocks,
        ]);

        $response = wp_remote_post($webhook_url, [
            'body'     => $payload,
            'headers'  => ['Content-Type' => 'application/json'],
            'timeout'  => 5,
            'blocking' => $blocking,
        ]);

        if ($blocking) {
            if (is_wp_error($response)) {
                error_log('[HVAC Slack] Send failed: ' . $response->get_error_message());
                return false;
            }
            $code = wp_remote_retrieve_response_code($response);
            if ($code !== 200) {
                $body = wp_remote_retrieve_body($response);
                error_log("[HVAC Slack] Slack returned HTTP {$code}: {$body}");
                return false;
            }
            return true;
        }

        // Non-blocking — optimistically assume success
        if (is_wp_error($response)) {
            error_log('[HVAC Slack] Non-blocking send error: ' . $response->get_error_message());
        }

        return true;
    }

    // ------------------------------------------------------------------
    // Registration notification
    // ------------------------------------------------------------------

    /**
     * Send a Slack notification for a new trainer registration.
     *
     * @param int   $user_id        Newly created user ID.
     * @param array $submitted_data Raw form data from registration.
     */
    public static function notify_new_registration(int $user_id, array $submitted_data): void {
        $first_name    = sanitize_text_field($submitted_data['first_name'] ?? 'N/A');
        $last_name     = sanitize_text_field($submitted_data['last_name'] ?? '');
        $full_name     = trim("{$first_name} {$last_name}") ?: 'N/A';
        $role          = sanitize_text_field($submitted_data['role'] ?? $submitted_data['trainer_type'] ?? 'Trainer');
        $business_name = sanitize_text_field($submitted_data['business_name'] ?? $submitted_data['company'] ?? 'N/A');
        $business_type = sanitize_text_field($submitted_data['business_type'] ?? 'N/A');

        $admin_url = admin_url("user-edit.php?user_id={$user_id}");
        $text      = "New Trainer Registration: {$full_name} ({$role})";

        // Profile image accessory (optional)
        $accessory = null;
        $image_id  = get_user_meta($user_id, 'profile_image_id', true);
        if ($image_id) {
            $image_url = wp_get_attachment_image_url((int) $image_id, 'thumbnail');
            if ($image_url) {
                $accessory = [
                    'type'      => 'image',
                    'image_url' => $image_url,
                    'alt_text'  => $full_name,
                ];
            }
        }

        $fields_section = [
            'type'   => 'section',
            'fields' => [
                ['type' => 'mrkdwn', 'text' => "*Name:*\n{$full_name}"],
                ['type' => 'mrkdwn', 'text' => "*Role:*\n{$role}"],
                ['type' => 'mrkdwn', 'text' => "*Organization:*\n{$business_name}"],
                ['type' => 'mrkdwn', 'text' => "*Business Type:*\n{$business_type}"],
            ],
        ];

        if ($accessory) {
            $fields_section['accessory'] = $accessory;
        }

        $blocks = [
            [
                'type' => 'header',
                'text' => ['type' => 'plain_text', 'text' => "\xF0\x9F\x86\x95 New Trainer Registration", 'emoji' => true],
            ],
            $fields_section,
            [
                'type'     => 'actions',
                'elements' => [
                    [
                        'type'  => 'button',
                        'text'  => ['type' => 'plain_text', 'text' => 'View in WordPress'],
                        'url'   => $admin_url,
                        'style' => 'primary',
                    ],
                ],
            ],
        ];

        self::send($text, $blocks);
    }

    // ------------------------------------------------------------------
    // Ticket purchase notification
    // ------------------------------------------------------------------

    /**
     * Hook callback for transition_post_status.
     *
     * @param string  $new_status New post status.
     * @param string  $old_status Previous post status.
     * @param WP_Post $post       Post object.
     */
    public static function on_order_status_change(string $new_status, string $old_status, \WP_Post $post): void {
        // Guard 1: correct post type
        if ($post->post_type !== 'tec_tc_order') {
            return;
        }

        // Guard 2: transitioning INTO completed
        if ($new_status !== 'tec-tc-completed') {
            return;
        }

        // Guard 3: not already completed (prevents re-saves)
        if ($old_status === 'tec-tc-completed') {
            return;
        }

        // Atomic idempotency: add_post_meta with $unique=true prevents races
        if (!add_post_meta($post->ID, '_hvac_slack_ticket_notified', '1', true)) {
            return;
        }

        self::notify_ticket_purchase($post->ID);
    }

    /**
     * Send a Slack notification for a completed ticket purchase.
     *
     * @param int $order_id TEC Tickets Commerce order post ID.
     */
    public static function notify_ticket_purchase(int $order_id): void {
        $purchaser_name  = get_post_meta($order_id, '_tec_tc_order_purchaser_name', true) ?: 'N/A';
        $purchaser_email = get_post_meta($order_id, '_tec_tc_order_purchaser_email', true) ?: 'N/A';
        $order_items     = get_post_meta($order_id, '_tec_tc_order_items', true);
        $gateway         = get_post_meta($order_id, '_tec_tc_order_gateway', true) ?: 'Unknown';

        $total_qty   = 0;
        $total_price = 0.0;
        $event_title = 'N/A';

        if (is_array($order_items)) {
            foreach ($order_items as $item) {
                $qty          = (int) ($item['quantity'] ?? 1);
                $total_qty   += $qty;
                $total_price += (float) ($item['sub_total'] ?? $item['price'] ?? 0) * $qty;

                if (!empty($item['event_id']) && $event_title === 'N/A') {
                    $title = get_the_title((int) $item['event_id']);
                    if ($title) {
                        $event_title = $title;
                    }
                }
            }
        }

        $total_formatted = '$' . number_format($total_price, 2);
        $admin_url       = admin_url("post.php?post={$order_id}&action=edit");
        $text            = "New Ticket Purchase: {$purchaser_name} — {$total_qty} ticket(s) for {$event_title} ({$total_formatted})";

        $blocks = [
            [
                'type' => 'header',
                'text' => ['type' => 'plain_text', 'text' => "\xF0\x9F\x8E\x9F\xEF\xB8\x8F New Ticket Purchase", 'emoji' => true],
            ],
            [
                'type'   => 'section',
                'fields' => [
                    ['type' => 'mrkdwn', 'text' => "*Purchaser:*\n{$purchaser_name}"],
                    ['type' => 'mrkdwn', 'text' => "*Email:*\n{$purchaser_email}"],
                    ['type' => 'mrkdwn', 'text' => "*Event:*\n{$event_title}"],
                    ['type' => 'mrkdwn', 'text' => "*Tickets:*\n{$total_qty}"],
                ],
            ],
            [
                'type'   => 'section',
                'fields' => [
                    ['type' => 'mrkdwn', 'text' => "*Total:*\n{$total_formatted}"],
                ],
            ],
            [
                'type'     => 'context',
                'elements' => [
                    ['type' => 'mrkdwn', 'text' => "via {$gateway}"],
                ],
            ],
            [
                'type'     => 'actions',
                'elements' => [
                    [
                        'type'  => 'button',
                        'text'  => ['type' => 'plain_text', 'text' => 'View Order'],
                        'url'   => $admin_url,
                        'style' => 'primary',
                    ],
                ],
            ],
        ];

        self::send($text, $blocks);
    }

    // ------------------------------------------------------------------
    // Event notifications
    // ------------------------------------------------------------------

    /**
     * Build common event Block Kit fields from an event post ID.
     *
     * @param int $event_id The tribe_events post ID.
     * @return array{text: string, fields: array, admin_url: string, event_title: string}
     */
    private static function build_event_fields(int $event_id): array {
        $event = get_post($event_id);
        $event_title = $event ? $event->post_title : 'N/A';

        $start_date = get_post_meta($event_id, '_EventStartDate', true);
        $end_date   = get_post_meta($event_id, '_EventEndDate', true);
        $venue_id   = get_post_meta($event_id, '_EventVenueID', true);
        $venue_name = $venue_id ? get_the_title((int) $venue_id) : 'N/A';

        $date_display = 'N/A';
        if ($start_date) {
            $date_display = wp_date('M j, Y g:ia', strtotime($start_date));
            if ($end_date) {
                $date_display .= ' — ' . wp_date('g:ia', strtotime($end_date));
            }
        }

        // Get trainer/author info
        $author_id   = $event ? (int) $event->post_author : 0;
        $author_name = $author_id ? get_the_author_meta('display_name', $author_id) : 'N/A';

        $admin_url = admin_url("post.php?post={$event_id}&action=edit");
        $front_url = get_permalink($event_id) ?: $admin_url;

        $fields = [
            ['type' => 'mrkdwn', 'text' => "*Event:*\n{$event_title}"],
            ['type' => 'mrkdwn', 'text' => "*Trainer:*\n{$author_name}"],
            ['type' => 'mrkdwn', 'text' => "*Date:*\n{$date_display}"],
            ['type' => 'mrkdwn', 'text' => "*Venue:*\n{$venue_name}"],
        ];

        return [
            'event_title' => $event_title,
            'author_name' => $author_name,
            'fields'      => $fields,
            'admin_url'   => $admin_url,
            'front_url'   => $front_url,
        ];
    }

    /**
     * Called when a trainer submits an event via TEC Community Events form.
     * Hooked to `hvac_tec_event_saved`.
     *
     * @param int $event_id The saved event post ID.
     */
    public static function notify_event_submitted(int $event_id): void {
        // Atomic lock: add_post_meta with $unique=true returns false if key already exists.
        // Prevents duplicate sends on edits and concurrent requests.
        if (!add_post_meta($event_id, '_hvac_slack_event_notified', '1', true)) {
            return;
        }

        $data = self::build_event_fields($event_id);
        $text = "New Event Submitted: {$data['event_title']} by {$data['author_name']}";

        $blocks = [
            [
                'type' => 'header',
                'text' => ['type' => 'plain_text', 'text' => "\xF0\x9F\x93\x9D Event Submitted by Trainer", 'emoji' => true],
            ],
            [
                'type'   => 'section',
                'fields' => $data['fields'],
            ],
            [
                'type'     => 'actions',
                'elements' => [
                    [
                        'type'  => 'button',
                        'text'  => ['type' => 'plain_text', 'text' => 'View Event'],
                        'url'   => $data['admin_url'],
                        'style' => 'primary',
                    ],
                ],
            ],
        ];

        self::send($text, $blocks);
    }

    /**
     * Hook callback for transition_post_status on tribe_events.
     * Fires when an admin publishes an event (including from draft/pending).
     *
     * @param string  $new_status New post status.
     * @param string  $old_status Previous post status.
     * @param WP_Post $post       Post object.
     */
    public static function on_event_status_change(string $new_status, string $old_status, \WP_Post $post): void {
        if ($post->post_type !== 'tribe_events') {
            return;
        }

        // Only notify when transitioning INTO publish
        if ($new_status !== 'publish' || $old_status === 'publish') {
            return;
        }

        // Atomic lock: prevents double-notify from trainer submission hook or concurrent requests
        if (!add_post_meta($post->ID, '_hvac_slack_event_notified', '1', true)) {
            return;
        }

        $data = self::build_event_fields($post->ID);
        $text = "Event Published: {$data['event_title']}";

        $blocks = [
            [
                'type' => 'header',
                'text' => ['type' => 'plain_text', 'text' => "\xE2\x9C\x85 Event Published", 'emoji' => true],
            ],
            [
                'type'   => 'section',
                'fields' => $data['fields'],
            ],
            [
                'type'     => 'actions',
                'elements' => [
                    [
                        'type'  => 'button',
                        'text'  => ['type' => 'plain_text', 'text' => 'View Event'],
                        'url'   => $data['front_url'],
                    ],
                    [
                        'type'  => 'button',
                        'text'  => ['type' => 'plain_text', 'text' => 'Edit in WP'],
                        'url'   => $data['admin_url'],
                    ],
                ],
            ],
        ];

        self::send($text, $blocks);
    }

    // ------------------------------------------------------------------
    // Test notification (AJAX)
    // ------------------------------------------------------------------

    /**
     * AJAX handler: send a test notification to verify webhook config.
     * Uses blocking mode so the admin UI gets real success/failure feedback.
     */
    public static function send_test_notification(): void {
        if (!current_user_can('manage_options')) {
            wp_send_json_error(['message' => 'Unauthorized'], 403);
        }

        check_ajax_referer('hvac_test_slack_webhook', 'nonce');

        $env      = function_exists('hvac_is_staging_environment') && hvac_is_staging_environment() ? 'Staging' : 'Production';
        $site_url = home_url('/');

        $text   = "Test notification from HVAC Community Events ({$env})";
        $blocks = [
            [
                'type' => 'header',
                'text' => ['type' => 'plain_text', 'text' => "\xE2\x9C\x85 Slack Integration Test", 'emoji' => true],
            ],
            [
                'type' => 'section',
                'text' => [
                    'type' => 'mrkdwn',
                    'text' => "This is a test notification from *HVAC Community Events*.\nIf you see this, your webhook is working correctly.",
                ],
            ],
            [
                'type'   => 'section',
                'fields' => [
                    ['type' => 'mrkdwn', 'text' => "*Environment:*\n{$env}"],
                    ['type' => 'mrkdwn', 'text' => "*Site:*\n{$site_url}"],
                ],
            ],
            [
                'type'     => 'context',
                'elements' => [
                    ['type' => 'mrkdwn', 'text' => 'Sent at ' . current_time('Y-m-d H:i:s')],
                ],
            ],
        ];

        $result = self::send($text, $blocks, blocking: true);

        if ($result === null) {
            wp_send_json_error(['message' => 'No webhook URL configured.']);
        } elseif ($result === false) {
            wp_send_json_error(['message' => 'Slack returned an error. Check the webhook URL and try again.']);
        } else {
            wp_send_json_success(['message' => 'Test notification sent successfully!']);
        }
    }
}
