<?php
/**
 * NotificationChannelsTable — standalone class file.
 *
 * @package UltraguardPro\modules\notifications\db
 */

namespace UltraguardPro\modules\notifications\db;

use UltraguardPro\db\BaseTable;
use UltraguardPro\core\DataCodec;

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

/**
 * NotificationChannelsTable — Saved reusable delivery destinations.
 *
 * Allows admins to configure named channels (e.g. "DevOps Slack", "CTO Email")
 * that can be referenced by multiple rules without repeating credentials.
 *
 * @package UltraguardPro\modules\notifications\db
 * @since   6.5.0
 */
class NotificationChannelsTable extends BaseTable {

    protected $table_name  = 'ultraguard_notification_channels';
    protected $cache_group = 'ultraguard_notification_channels';

    public function get_defaults(): array {
        return [
            'id'             => 0,
            'name'           => '',
            'channel_type'   => 'email',
            'address'        => '',
            'webhook_secret' => null,
            'config_json'    => null,
            'is_active'      => 1,
            'last_tested_at' => null,
            'test_status'    => null,
            'created_by'     => null,
            'created_at'     => '',
            'updated_at'     => '',
        ];
    }

    protected function validate_data( $data ) {
        if ( empty( $data['name'] ) || empty( $data['address'] ) ) { return false; }

        $valid_types = [ 'email', 'webhook', 'slack', 'admin_notice', 'sms' ];
        if ( isset( $data['channel_type'] ) && ! in_array( $data['channel_type'], $valid_types, true ) ) {
            $data['channel_type'] = 'email';
        }

        return $data;
    }

    protected function sanitize_data( $data ): array {
        $out = [];
        foreach ( $data as $k => $v ) {
            $out[ $k ] = match ( $k ) {
                'config_json'    => is_null( $v ) ? null : ( is_array( $v ) ? wp_json_encode( $v ) : sanitize_textarea_field( (string) $v ) ),
                'webhook_secret' => is_null( $v ) ? null : sanitize_text_field( (string) $v ),
                'is_active'      => (int) (bool) $v,
                'created_by'     => is_null( $v ) ? null : absint( $v ),
                'address'        => sanitize_text_field( substr( (string) $v, 0, 500 ) ),
                default          => is_string( $v ) ? sanitize_text_field( $v ) : $v,
            };
        }
        return $out;
    }

    // ── DataCodec integration ───────────────────────────────────────────────────

    /**
     * 'config_json' stores a JSON blob (PHP array encoded with wp_json_encode).
     * The JSON value may contain HTML-like tokens (webhook headers, template keys)
     * that sanitize_textarea_field() / wp_strip_all_tags() would destroy.
     * DataCodec Base64-wraps on write and decodes back to a PHP array on read.
     *
     * @return string[]
     */
    protected function get_codec_fields(): array {
        return [ 'config_json' ];
    }

    /**
     * 'config_json' payloads are JSON arrays — decode back to PHP arrays on read.
     *
     * @return string[]
     */
    protected function get_json_codec_fields(): array {
        return [ 'config_json' ];
    }

    protected function get_searchable_fields(): array {
        return [ 'name', 'channel_type', 'address' ];
    }

    // ── Domain methods ─────────────────────────────────────────────────────────

    /**
     * Mark a channel's last test result.
     *
     * @param  int    $id
     * @param  bool   $success
     * @return bool
     */
    public function record_test( int $id, bool $success ): bool {
        return $this->update( $id, [
            'last_tested_at' => current_time( 'mysql', true ),
            'test_status'    => $success ? 'ok' : 'failed',
        ] );
    }

    /**
     * Get all active channels grouped by type.
     *
     * @return array  ['email' => [...], 'webhook' => [...], ...]
     */
    public function get_by_type_grouped(): array {
        $all    = $this->get_by( [ 'is_active' => 1 ], 500, 'name', 'ASC' );
        $groups = [];
        foreach ( $all as $ch ) {
            $type = $ch['channel_type'] ?? 'email';
            $groups[ $type ][] = $ch;
        }
        return $groups;
    }
}
