<?php
/**
 * Announcement Manager Library for Web Hosting Panel
 * Handles server announcements CRUD operations
 */

class announcement_manager {
    
    private $db;
    
    public function __construct() {
        $this->db = $this->get_mysql_connection();
    }
    
    /**
     * Get MySQL connection
     */
    private function get_mysql_connection() {
        try {
            require_once('/docker/whp/web/libs/mysqlmgmt.php');
            $MySQLMgmt = new mysqlmgmt();
            $pdo = $MySQLMgmt->getMySQLConnection();
            
            // Ensure the whp database exists
            if ($pdo) {
                try {
                    $pdo->exec("CREATE DATABASE IF NOT EXISTS whp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
                    $pdo->exec("USE whp");
                    
                    // Ensure the announcements table exists
                    $pdo->exec("
                        CREATE TABLE IF NOT EXISTS announcements (
                            id INT AUTO_INCREMENT PRIMARY KEY,
                            title VARCHAR(255) NOT NULL,
                            content TEXT NOT NULL,
                            markdown_content TEXT NOT NULL,
                            created_by VARCHAR(32) NOT NULL,
                            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                            updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                            active BOOLEAN DEFAULT TRUE,
                            priority INT DEFAULT 0,
                            pinned BOOLEAN DEFAULT FALSE,
                            INDEX idx_active (active),
                            INDEX idx_priority (priority),
                            INDEX idx_pinned (pinned),
                            INDEX idx_created_by (created_by),
                            INDEX idx_created_at (created_at)
                        )
                    ");
                    
                } catch (PDOException $e) {
                    error_log("Failed to create/use whp database or announcements table: " . $e->getMessage());
                }
            }
            
            return $pdo;
        } catch (Exception $e) {
            error_log("Failed to connect to MySQL for announcements: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Get all active announcements ordered by pinned status, priority and date
     * 
     * @return array Array of announcements
     */
    public function get_active_announcements() {
        if (!$this->db) {
            return [];
        }
        
        try {
            $stmt = $this->db->prepare("
                SELECT id, title, content, markdown_content, created_by, created_at, priority, pinned 
                FROM announcements 
                WHERE active = 1 
                ORDER BY pinned DESC, priority DESC, created_at DESC
            ");
            $stmt->execute();
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            error_log("Failed to get active announcements: " . $e->getMessage());
            return [];
        }
    }
    
    /**
     * Get all announcements (for management page)
     * 
     * @return array Array of all announcements
     */
    public function get_all_announcements() {
        if (!$this->db) {
            return [];
        }
        
        try {
            $stmt = $this->db->prepare("
                SELECT id, title, content, markdown_content, created_by, created_at, updated_at, active, priority, pinned 
                FROM announcements 
                ORDER BY pinned DESC, priority DESC, created_at DESC
            ");
            $stmt->execute();
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            error_log("Failed to get all announcements: " . $e->getMessage());
            return [];
        }
    }
    
    /**
     * Get a single announcement by ID
     * 
     * @param int $id Announcement ID
     * @return array|null Announcement data or null if not found
     */
    public function get_announcement($id) {
        if (!$this->db) {
            return null;
        }
        
        try {
            $stmt = $this->db->prepare("
                SELECT id, title, content, markdown_content, created_by, created_at, updated_at, active, priority, pinned 
                FROM announcements 
                WHERE id = ?
            ");
            $stmt->execute([$id]);
            return $stmt->fetch(PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            error_log("Failed to get announcement $id: " . $e->getMessage());
            return null;
        }
    }
    
    /**
     * Create a new announcement
     * 
     * @param string $title Announcement title
     * @param string $markdown_content Markdown content
     * @param string $created_by Username of creator
     * @param int $priority Priority level (default 0)
     * @param bool $active Whether announcement is active (default true)
     * @param bool $pinned Whether announcement is pinned (default false)
     * @return array Status array with success/error information
     */
    public function create_announcement($title, $markdown_content, $created_by, $priority = 0, $active = true, $pinned = false) {
        if (!$this->db) {
            return ['status' => 'error', 'message' => 'Database connection failed'];
        }
        
        if (empty($title) || empty($markdown_content)) {
            return ['status' => 'error', 'message' => 'Title and content are required'];
        }
        
        // Convert markdown to HTML
        $html_content = $this->markdown_to_html($markdown_content);
        
        try {
            $stmt = $this->db->prepare("
                INSERT INTO announcements (title, content, markdown_content, created_by, priority, active, pinned) 
                VALUES (?, ?, ?, ?, ?, ?, ?)
            ");
            $stmt->execute([$title, $html_content, $markdown_content, $created_by, $priority, $active ? 1 : 0, $pinned ? 1 : 0]);
            
            return ['status' => 'success', 'message' => 'Announcement created successfully', 'id' => $this->db->lastInsertId()];
        } catch (PDOException $e) {
            error_log("Failed to create announcement: " . $e->getMessage());
            return ['status' => 'error', 'message' => 'Failed to create announcement: ' . $e->getMessage()];
        }
    }
    
    /**
     * Update an existing announcement
     * 
     * @param int $id Announcement ID
     * @param string $title Announcement title
     * @param string $markdown_content Markdown content
     * @param int $priority Priority level
     * @param bool $active Whether announcement is active
     * @param bool $pinned Whether announcement is pinned
     * @return array Status array with success/error information
     */
    public function update_announcement($id, $title, $markdown_content, $priority = 0, $active = true, $pinned = false) {
        if (!$this->db) {
            return ['status' => 'error', 'message' => 'Database connection failed'];
        }
        
        if (empty($title) || empty($markdown_content)) {
            return ['status' => 'error', 'message' => 'Title and content are required'];
        }
        
        // Convert markdown to HTML
        $html_content = $this->markdown_to_html($markdown_content);
        
        try {
            $stmt = $this->db->prepare("
                UPDATE announcements 
                SET title = ?, content = ?, markdown_content = ?, priority = ?, active = ?, pinned = ? 
                WHERE id = ?
            ");
            $stmt->execute([$title, $html_content, $markdown_content, $priority, $active ? 1 : 0, $pinned ? 1 : 0, $id]);
            
            if ($stmt->rowCount() > 0) {
                return ['status' => 'success', 'message' => 'Announcement updated successfully'];
            } else {
                return ['status' => 'error', 'message' => 'Announcement not found or no changes made'];
            }
        } catch (PDOException $e) {
            error_log("Failed to update announcement $id: " . $e->getMessage());
            return ['status' => 'error', 'message' => 'Failed to update announcement: ' . $e->getMessage()];
        }
    }
    
    /**
     * Delete an announcement
     * 
     * @param int $id Announcement ID
     * @return array Status array with success/error information
     */
    public function delete_announcement($id) {
        if (!$this->db) {
            return ['status' => 'error', 'message' => 'Database connection failed'];
        }
        
        try {
            $stmt = $this->db->prepare("DELETE FROM announcements WHERE id = ?");
            $stmt->execute([$id]);
            
            if ($stmt->rowCount() > 0) {
                return ['status' => 'success', 'message' => 'Announcement deleted successfully'];
            } else {
                return ['status' => 'error', 'message' => 'Announcement not found'];
            }
        } catch (PDOException $e) {
            error_log("Failed to delete announcement $id: " . $e->getMessage());
            return ['status' => 'error', 'message' => 'Failed to delete announcement: ' . $e->getMessage()];
        }
    }
    
    /**
     * Toggle announcement active status
     * 
     * @param int $id Announcement ID
     * @return array Status array with success/error information
     */
    public function toggle_announcement_status($id) {
        if (!$this->db) {
            return ['status' => 'error', 'message' => 'Database connection failed'];
        }
        
        try {
            $stmt = $this->db->prepare("UPDATE announcements SET active = NOT active WHERE id = ?");
            $stmt->execute([$id]);
            
            if ($stmt->rowCount() > 0) {
                return ['status' => 'success', 'message' => 'Announcement status updated successfully'];
            } else {
                return ['status' => 'error', 'message' => 'Announcement not found'];
            }
        } catch (PDOException $e) {
            error_log("Failed to toggle announcement status $id: " . $e->getMessage());
            return ['status' => 'error', 'message' => 'Failed to update announcement status: ' . $e->getMessage()];
        }
    }
    
    /**
     * Toggle announcement pinned status
     * 
     * @param int $id Announcement ID
     * @return array Status array with success/error information
     */
    public function toggle_announcement_pinned($id) {
        if (!$this->db) {
            return ['status' => 'error', 'message' => 'Database connection failed'];
        }
        
        try {
            $stmt = $this->db->prepare("UPDATE announcements SET pinned = NOT pinned WHERE id = ?");
            $stmt->execute([$id]);
            
            if ($stmt->rowCount() > 0) {
                return ['status' => 'success', 'message' => 'Announcement pin status updated successfully'];
            } else {
                return ['status' => 'error', 'message' => 'Announcement not found'];
            }
        } catch (PDOException $e) {
            error_log("Failed to toggle announcement pinned status $id: " . $e->getMessage());
            return ['status' => 'error', 'message' => 'Failed to update announcement pin status: ' . $e->getMessage()];
        }
    }
    
    /**
     * Simple markdown to HTML converter
     * This is a basic implementation - you might want to use a more robust library
     * 
     * @param string $markdown Markdown content
     * @return string HTML content
     */
    private function markdown_to_html($markdown) {
        // Basic markdown conversions
        $html = $markdown;
        
        // Headers (allow optional leading whitespace)
        $html = preg_replace('/^\s*### (.*$)/m', '<h3>$1</h3>', $html);
        $html = preg_replace('/^\s*## (.*$)/m', '<h2>$1</h2>', $html);
        $html = preg_replace('/^\s*# (.*$)/m', '<h1>$1</h1>', $html);
        
        // Bold and italic
        $html = preg_replace('/\*\*(.*?)\*\*/', '<strong>$1</strong>', $html);
        $html = preg_replace('/\*(.*?)\*/', '<em>$1</em>', $html);
        
        // Links
        $html = preg_replace('/\[([^\]]+)\]\(([^)]+)\)/', '<a href="$2">$1</a>', $html);
        
        // Code blocks
        $html = preg_replace('/```([^`]+)```/s', '<pre><code>$1</code></pre>', $html);
        $html = preg_replace('/`([^`]+)`/', '<code>$1</code>', $html);
        
        // Lists - convert items then wrap consecutive <li> blocks in <ul>,
        // removing newlines between items so they don't become <br> later
        $html = preg_replace('/^\s*- (.*)$/m', '<li>$1</li>', $html);
        $html = preg_replace('/(<\/li>)\n(<li>)/', '$1$2', $html);
        $html = preg_replace('/(<li>.*<\/li>)/s', '<ul>$1</ul>', $html);
        
        // Ensure block-level elements (headings, lists, pre) are separated by double newlines
        // so they become their own paragraphs and don't get stuck inside <p> tags
        $html = preg_replace('/\n?(<h[1-6]>.*?<\/h[1-6]>)\n?/', "\n\n$1\n\n", $html);
        $html = preg_replace('/\n?(<ul>.*?<\/ul>)\n?/s', "\n\n$1\n\n", $html);
        $html = preg_replace('/\n?(<pre>.*?<\/pre>)\n?/s', "\n\n$1\n\n", $html);

        // Line breaks - handle both single and double newlines
        // First, convert double newlines to paragraph breaks
        $html = preg_replace('/\n\n+/', '</p><p>', $html);
        // Then convert remaining single newlines to <br> tags
        $html = preg_replace('/\n/', '<br>', $html);
        $html = '<p>' . $html . '</p>';

        // Clean up: remove block elements from inside <p> tags
        $html = preg_replace('/<p><\/p>/', '', $html);
        $html = preg_replace('/<p>\s*(<h[1-6]>.*?<\/h[1-6]>)\s*<\/p>/', '$1', $html);
        $html = preg_replace('/<p>\s*(<ul>.*?<\/ul>)\s*<\/p>/s', '$1', $html);
        $html = preg_replace('/<p>\s*(<pre>.*?<\/pre>)\s*<\/p>/s', '$1', $html);
        // Remove stray <br> right before/after block elements
        $html = preg_replace('/<br>\s*(<h[1-6]>)/', '$1', $html);
        $html = preg_replace('/(<\/h[1-6]>)\s*<br>/', '$1', $html);
        $html = preg_replace('/<br>\s*(<ul>)/', '$1', $html);
        $html = preg_replace('/(<\/ul>)\s*<br>/', '$1', $html);
        
        return $html;
    }
}
?> 