<?php
/**
 * Announcement Model
 * Maps to `announcements` and `announcement_history` tables
 */

require_once __DIR__ . '/../Core/Model.php';

class Announcement extends Model {
    protected string $table = 'announcements';

    /**
     * Get Active Announcements for specific placement and audience
     */
    public function getActiveAnnouncements(string $location, string $audience = 'all'): array {
        $params = [':location' => $location];
        $audienceSql = "1=1";

        if ($audience !== 'all') {
            $audienceSql = "(`target_audience` = :audience OR `target_audience` = 'all')";
            $params[':audience'] = $audience;
        }

        $sql = "SELECT * FROM `announcements`
                WHERE `status` = 'active'
                AND `deleted_at` IS NULL
                AND {$audienceSql}
                AND `display_location` = :location
                AND (`start_at` IS NULL OR `start_at` <= NOW())
                AND (`end_at` IS NULL OR `end_at` >= NOW())
                ORDER BY CASE `priority` 
                    WHEN 'critical' THEN 1 
                    WHEN 'important' THEN 2 
                    ELSE 3 
                END ASC, `created_at` DESC";

        return $this->fetchAll($sql, $params);
    }

    /**
     * Admin: Get all announcements with filtering
     */
    public function getAdminAnnouncements(array $filters = [], int $limit = 20, int $offset = 0): array {
        [$whereSql, $params] = $this->buildFilterConditions($filters);

        $sql = "SELECT a.*, u.username as creator_username
                FROM `announcements` a
                LEFT JOIN `users` u ON a.created_by = u.id
                WHERE {$whereSql}
                ORDER BY a.created_at DESC
                LIMIT :limit OFFSET :offset";

        $stmt = $this->db->prepare($sql);
        foreach ($params as $k => $v) {
            $stmt->bindValue($k, $v);
        }
        $stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
        $stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
        $stmt->execute();

        return $stmt->fetchAll();
    }

    public function countAdminAnnouncements(array $filters = []): int {
        [$whereSql, $params] = $this->buildFilterConditions($filters);

        $sql = "SELECT COUNT(*) FROM `announcements` a WHERE {$whereSql}";
        $stmt = $this->db->prepare($sql);
        foreach ($params as $k => $v) {
            $stmt->bindValue($k, $v);
        }
        $stmt->execute();

        return (int)$stmt->fetchColumn();
    }

    private function buildFilterConditions(array $filters): array {
        $conditions = ["a.deleted_at IS NULL"];
        $params = [];

        if (!empty($filters['q'])) {
            $conditions[] = "(a.title LIKE :kw OR a.content LIKE :kw)";
            $params[':kw'] = '%' . trim($filters['q']) . '%';
        }

        if (!empty($filters['status']) && $filters['status'] !== 'all') {
            $conditions[] = "a.status = :status";
            $params[':status'] = $filters['status'];
        }

        if (!empty($filters['target_audience']) && $filters['target_audience'] !== 'all') {
            $conditions[] = "a.target_audience = :audience";
            $params[':audience'] = $filters['target_audience'];
        }

        if (!empty($filters['display_location']) && $filters['display_location'] !== 'all') {
            $conditions[] = "a.display_location = :location";
            $params[':location'] = $filters['display_location'];
        }

        if (!empty($filters['priority']) && $filters['priority'] !== 'all') {
            $conditions[] = "a.priority = :priority";
            $params[':priority'] = $filters['priority'];
        }

        return [implode(" AND ", $conditions), $params];
    }

    /**
     * Create Announcement and record history
     */
    public function createAnnouncement(array $data, int $adminId): int {
        $data['created_by'] = $adminId;
        $data['created_at'] = date('Y-m-d H:i:s');
        $data['updated_at'] = date('Y-m-d H:i:s');

        $announcementId = $this->insert($data);

        $this->logHistory($announcementId, 'created', $adminId, "Created announcement: {$data['title']}");

        return $announcementId;
    }

    /**
     * Update Announcement and record history
     */
    public function updateAnnouncement(int $id, array $data, int $adminId): bool {
        $data['updated_by'] = $adminId;
        $data['updated_at'] = date('Y-m-d H:i:s');

        $this->update($id, $data);
        $this->logHistory($id, 'updated', $adminId, "Updated announcement details");

        return true;
    }

    /**
     * Toggle Publish / Pause (active / disabled)
     */
    public function toggleStatus(int $id, int $adminId): string {
        $ann = $this->findById($id);
        if (!$ann) {
            return 'not_found';
        }

        $newStatus = ($ann['status'] === 'active') ? 'disabled' : 'active';
        $this->update($id, [
            'status' => $newStatus,
            'updated_by' => $adminId,
            'updated_at' => date('Y-m-d H:i:s')
        ]);

        $this->logHistory($id, 'status_changed', $adminId, "Changed status from {$ann['status']} to {$newStatus}");

        return $newStatus;
    }

    /**
     * Soft delete announcement
     */
    public function softDeleteAnnouncement(int $id, int $adminId): bool {
        $sql = "UPDATE `announcements` SET `deleted_at` = NOW(), `status` = 'disabled', `updated_by` = :admin_id WHERE `id` = :id";
        $stmt = $this->query($sql, [':admin_id' => $adminId, ':id' => $id]);

        $this->logHistory($id, 'deleted', $adminId, "Deleted announcement #{$id}");

        return $stmt->rowCount() > 0;
    }

    /**
     * Log action into announcement_history
     */
    public function logHistory(int $announcementId, string $action, int $performedBy, ?string $details = null): void {
        $sql = "INSERT INTO `announcement_history` (`announcement_id`, `action`, `performed_by`, `details`, `created_at`) 
                VALUES (:aid, :act, :by, :details, NOW())";
        $this->query($sql, [
            ':aid' => $announcementId,
            ':act' => $action,
            ':by' => $performedBy,
            ':details' => $details
        ]);
    }

    /**
     * Get Audit History of an Announcement
     */
    public function getHistory(int $announcementId): array {
        $sql = "SELECT h.*, u.username as performer_username, u.first_name, u.last_name
                FROM `announcement_history` h
                LEFT JOIN `users` u ON h.performed_by = u.id
                WHERE h.announcement_id = :aid
                ORDER BY h.created_at DESC";
        return $this->fetchAll($sql, [':aid' => $announcementId]);
    }

    /**
     * Increment View and Click counts
     */
    public function incrementViewCount(int $id): void {
        $sql = "UPDATE `announcements` SET `view_count` = `view_count` + 1 WHERE `id` = :id";
        $this->query($sql, [':id' => $id]);
    }

    public function incrementClickCount(int $id): void {
        $sql = "UPDATE `announcements` SET `click_count` = `click_count` + 1 WHERE `id` = :id";
        $this->query($sql, [':id' => $id]);
    }
}
