<?php
declare(strict_types=1);


/**
 * Notification Manager
 *
 * @package ProRank\Core
 */

namespace ProRank\SEO\Core;

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


/**
 * Manages admin notifications
 */


class NotificationManager {
    
    /**
     * Notifications option name
     *
     * @var string
     */
    private const OPTION_NAME = 'prorank_notifications';
    
    /**
     * Notifications cache
     *
     * @var array
     */
    private array $notifications = [];
    
    /**
     * Constructor
     */
    public function __construct() {
        add_action( 'admin_notices', [ $this, 'display_notices' ] );
        add_action( 'admin_init', [ $this, 'load_notifications' ] );
    }
    
    /**
     * Add a notification
     *
     * @param string $id Notification ID
     * @param string $type Notification type (error, warning, success, info)
     * @param string $message Notification message
     * @param bool $dismissible Whether notification is dismissible
     * @param array $data Additional data (e.g., action links)
     */
    public function add( string $id, string $type, string $message, bool $dismissible = true, array $data = [] ): void {
        $this->notifications[ $id ] = [
            'type' => $type,
            'message' => $message,
            'dismissible' => $dismissible,
            'timestamp' => time(),
            'data' => $data,
        ];
        
        $this->save_notifications();
    }
    
    /**
     * Add a notice (alias for add)
     *
     * @param string $id Notification ID
     * @param string $type Notification type (error, warning, success, info)
     * @param string $message Notification message
     * @param bool $dismissible Whether notification is dismissible
     * @param array $data Additional data
     */
    public function add_notice( string $id, string $type, string $message, bool $dismissible = true, array $data = [] ): void {
        $this->add( $id, $type, $message, $dismissible, $data );
    }

    /**
     * Add an internal log entry (non-UI).
     *
     * @param string $message Log message
     * @param array $context Optional context
     * @return void
     */
    public function add_internal_log( string $message, array $context = [] ): void {
        if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
            $suffix = '';
            if ( ! empty( $context ) ) {
                $suffix = ' ' . wp_json_encode( $context );
            }
            prorank_log( '[ProRank SEO] ' . $message . $suffix );
        }
    }
    
    /**
     * Remove a notification
     *
     * @param string $id Notification ID
     */
    public function remove( string $id ): void {
        unset( $this->notifications[ $id ] );
        $this->save_notifications();
    }
    
    /**
     * Load notifications from database
     */
    public function load_notifications(): void {
        $this->notifications = get_option( self::OPTION_NAME, [] );
    }
    
    /**
     * Save notifications to database
     */
    private function save_notifications(): void {
        update_option( self::OPTION_NAME, $this->notifications );
    }
    
    /**
     * Display admin notices
     */
    public function display_notices(): void {
        if ( empty( $this->notifications ) ) {
            return;
        }
        
        foreach ( $this->notifications as $id => $notification ) {
            $class = 'notice notice-' . $notification['type'];
            if ( $notification['dismissible'] ) {
                $class .= ' is-dismissible';
            }
            
            printf(
                '<div class="%1$s" data-notice-id="%2$s"><p>%3$s</p></div>',
                esc_attr( $class ),
                esc_attr( $id ),
                wp_kses_post( $notification['message'] )
            );
        }
    }
    
    /**
     * Get notifications based on filters
     *
     * @param array $filters Optional filters
     * @return array
     */
    public function get_notifications( array $filters = [] ): array {
        $notifications = $this->notifications;
        
        // Apply filters
        if ( ! empty( $filters['type'] ) ) {
            $notifications = array_filter( $notifications, function( $notification ) use ( $filters ) {
                return $notification['type'] === $filters['type'];
            });
        }
        
        if ( ! empty( $filters['priority'] ) ) {
            $notifications = array_filter( $notifications, function( $notification ) use ( $filters ) {
                return isset( $notification['priority'] ) && $notification['priority'] === $filters['priority'];
            });
        }
        
        return array_values( $notifications );
    }
    
    /**
     * Get notification counts by type
     *
     * @return array
     */
    public function get_notification_counts(): array {
        $counts = [
            'total' => count( $this->notifications ),
            'error' => 0,
            'warning' => 0,
            'success' => 0,
            'info' => 0,
        ];
        
        foreach ( $this->notifications as $notification ) {
            if ( isset( $counts[ $notification['type'] ] ) ) {
                $counts[ $notification['type'] ]++;
            }
        }
        
        return $counts;
    }
    
    /**
     * Get unread notification count
     *
     * @return int
     */
    public function get_unread_count(): int {
        $unread_count = 0;
        foreach ( $this->notifications as $id => $notification ) {
            if ( ! $this->is_dismissed( $id ) ) {
                $unread_count++;
            }
        }
        return $unread_count;
    }
    
    /**
     * Get total notification count
     *
     * @return int
     */
    public function get_total_count(): int {
        return count( $this->notifications );
    }
    
    /**
     * Check if a notification is dismissed
     *
     * @param string $notification_id Notification ID
     * @return bool
     */
    private function is_dismissed( string $notification_id ): bool {
        $dismissed = get_user_meta( get_current_user_id(), 'prorank_dismissed_notices', true );
        return is_array( $dismissed ) && in_array( $notification_id, $dismissed, true );
    }
    
    /**
     * Dismiss a notification
     *
     * @param string $notification_id Notification ID
     * @return bool
     */
    public function dismiss_notification( string $notification_id ): bool {
        if ( isset( $this->notifications[ $notification_id ] ) ) {
            $this->remove( $notification_id );
            return true;
        }
        
        return false;
    }
    
    /**
     * Clear notifications cache
     */
    public function clear_cache(): void {
        $this->notifications = [];
        $this->save_notifications();
    }
}
