<?php
/** Basic failure-only email alerts for Social Publisher. */
if (!defined('ABSPATH')) { exit; }

final class Calliope_SP_Failure_Alerts {
    public const ENABLED_OPTION = 'calliope_sp_failure_alerts_enabled';
    public const EMAIL_OPTION = 'calliope_sp_failure_alert_email';
    private const SENT_TRANSIENT_PREFIX = 'calliope_sp_failure_alert_sent_';

    public static function is_enabled(): bool { return get_option(self::ENABLED_OPTION, '0') === '1'; }

    public static function get_recipient(): string {
        $saved = sanitize_email((string) get_option(self::EMAIL_OPTION, ''));
        if ($saved !== '' && is_email($saved)) { return $saved; }
        $admin = sanitize_email((string) get_option('admin_email', ''));
        return ($admin !== '' && is_email($admin)) ? $admin : '';
    }

    public static function maybe_send(string $job_id, array $job, array $results, array $report): bool {
        if (!self::is_enabled() || (int) ($report['failed_count'] ?? 0) <= 0) { return false; }
        $should_send = (bool) apply_filters('calliope_sp_basic_failure_alert_should_send', true, $job_id, $job, $results, $report);
        if (!$should_send) { return false; }
        $recipient = self::get_recipient();
        if ($recipient === '') { self::log('warning', 'failure_alert_recipient_missing', $job_id); return false; }
        $dedupe_key = self::dedupe_key($job_id);
        if (get_transient($dedupe_key)) { return false; }

        $failed = [];
        foreach ($results as $network => $result) {
            if (!is_array($result) || !empty($result['ok'])) { continue; }
            $status = sanitize_key((string) ($result['ui_status'] ?? $result['status'] ?? ''));
            if (in_array($status, ['pending', 'needs_review'], true) || !empty($result['pending']) || !empty($result['needs_review'])) { continue; }
            $network = sanitize_key((string) $network);
            if ($network === '') { continue; }
            $message = sanitize_text_field((string) ($result['user_message'] ?? $result['short_message'] ?? $result['error'] ?? ''));
            $failed[$network] = $message !== '' ? $message : __('Publication failed.', 'calliope-social-publisher');
        }
        if ($failed === []) { return false; }

        $site_name = wp_specialchars_decode((string) get_bloginfo('name'), ENT_QUOTES);
        if ($site_name === '') { $site_name = wp_parse_url(home_url('/'), PHP_URL_HOST) ?: 'WordPress'; }
        $subject = sprintf(__('[Social Publisher] Publication failed on %s', 'calliope-social-publisher'), $site_name);
        $source = self::source_label(sanitize_key((string) ($job['source'] ?? 'manual')));
        $history_url = admin_url('admin.php?page=calliope-social-publisher&tab=history');
        $summary = sanitize_text_field((string) ($report['summary'] ?? ''));
        $date = wp_date(get_option('date_format') . ' ' . get_option('time_format'));
        $labels = self::network_labels();
        $lines = [
            __('Social Publisher detected a publication with failed destinations.', 'calliope-social-publisher'), '',
            sprintf(__('Site: %s', 'calliope-social-publisher'), $site_name),
            sprintf(__('Date: %s', 'calliope-social-publisher'), $date),
            sprintf(__('Source: %s', 'calliope-social-publisher'), $source), '',
            __('Failed destinations:', 'calliope-social-publisher'),
        ];
        foreach ($failed as $network => $message) {
            $label = (string) ($labels[$network] ?? ucwords(str_replace('_', ' ', $network)));
            $lines[] = '- ' . $label . ': ' . $message;
        }
        if ($summary !== '') { $lines[] = ''; $lines[] = sprintf(__('Publication summary: %s', 'calliope-social-publisher'), $summary); }
        $lines[] = '';
        $lines[] = sprintf(__('Review Publication History: %s', 'calliope-social-publisher'), $history_url);
        $lines[] = '';
        $lines[] = __('This email is sent only when at least one destination fails.', 'calliope-social-publisher');

        $sent = wp_mail($recipient, $subject, implode("\n", $lines), ['Content-Type: text/plain; charset=UTF-8']);
        if ($sent) {
            set_transient($dedupe_key, 1, 7 * DAY_IN_SECONDS);
            self::log('success', 'failure_alert_sent', $job_id, ['failed_count' => count($failed)]);
            return true;
        }
        self::log('warning', 'failure_alert_send_failed', $job_id, ['failed_count' => count($failed)]);
        return false;
    }

    private static function network_labels(): array {
        $labels = [];
        $visuals = apply_filters('calliope_sp_network_visual_registry', []);
        if (is_array($visuals)) {
            foreach ($visuals as $network => $definition) {
                if (is_array($definition) && isset($definition['label'])) { $labels[sanitize_key((string) $network)] = sanitize_text_field((string) $definition['label']); }
            }
        }
        return $labels;
    }

    private static function source_label(string $source): string {
        switch ($source) {
            case 'history_retry': return __('History retry', 'calliope-social-publisher');
            case 'pro_schedule': case 'schedule': case 'scheduled': return __('Scheduled publication', 'calliope-social-publisher');
            case 'gutenberg': case 'automatic': case 'auto_post': return __('Automatic publication', 'calliope-social-publisher');
            default: return __('Manual publication', 'calliope-social-publisher');
        }
    }

    private static function dedupe_key(string $job_id): string { return self::SENT_TRANSIENT_PREFIX . substr(hash('sha256', sanitize_key($job_id)), 0, 32); }

    private static function log(string $level, string $event, string $job_id, array $extra = []): void {
        if (!class_exists('Calliope_SP_Logger')) { return; }
        $payload = array_merge(['event' => $event, 'job_id' => sanitize_key($job_id)], $extra);
        Calliope_SP_Logger::log('notifications', $level, wp_json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
    }
}
