<?php
namespace App\Controllers;

use App\Core\Database;
use App\Core\NotificationService;

class AdminNotificationBroadcastController
{
    protected function db()
    {
        return Database::getInstance();
    }

    private function startSession(): void
    {
        if (session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }
    }

    private function role(): string
    {
        return (string)($_SESSION['conference_role'] ?? $_SESSION['role'] ?? $_SESSION['user_role'] ?? '');
    }

    private function requireAccess(): void
    {
        $this->startSession();

        if (empty($_SESSION['user_id'])) {
            header("Location: /easychair/login");
            exit;
        }

        if (empty($_SESSION['conference_id'])) {
            header("Location: /easychair/select-conference");
            exit;
        }

        if (!in_array($this->role(), ['super_admin','org_admin','admin','organizer','conference_chair'], true)) {
            http_response_code(403);
            exit("Access denied.");
        }
    }

    private function conference(): array
    {
        $stmt = $this->db()->prepare("
            SELECT c.*, o.name AS org_name
            FROM conferences c
            LEFT JOIN organizations o ON o.id=c.org_id
            WHERE c.id=?
            LIMIT 1
        ");
        $stmt->execute([(int)$_SESSION['conference_id']]);
        $c = $stmt->fetch(\PDO::FETCH_ASSOC);

        if (!$c) {
            exit("Conference not found.");
        }

        if ($this->role() !== 'super_admin' && (int)$c['org_id'] !== (int)($_SESSION['org_id'] ?? 0)) {
            http_response_code(403);
            exit("Invalid organization access.");
        }

        return $c;
    }

    private function availableRoles(): array
    {
        $stmt = $this->db()->query("
            SELECT id, name, code
            FROM roles
            ORDER BY id
        ");
        return $stmt->fetchAll(\PDO::FETCH_ASSOC);
    }

    private function getRecipients(array $conference, string $targetMode, string $roleCode = '', string $email = ''): array
    {
        if ($targetMode === 'email') {
            $stmt = $this->db()->prepare("
                SELECT DISTINCT 
                    u.id,
                    u.email,
                    CONCAT(COALESCE(u.first_name,''),' ',COALESCE(u.last_name,'')) AS full_name,
                    r.code AS role_code
                FROM users u
                JOIN user_conferences uc ON uc.user_id=u.id
                JOIN roles r ON r.id=uc.role_id
                WHERE uc.conference_id=?
                  AND u.email=?
                LIMIT 1
            ");
            $stmt->execute([(int)$conference['id'], $email]);
            return $stmt->fetchAll(\PDO::FETCH_ASSOC);
        }

        if ($targetMode === 'role' && $roleCode !== '') {
            $stmt = $this->db()->prepare("
                SELECT DISTINCT 
                    u.id,
                    u.email,
                    CONCAT(COALESCE(u.first_name,''),' ',COALESCE(u.last_name,'')) AS full_name,
                    r.code AS role_code
                FROM user_conferences uc
                JOIN users u ON u.id=uc.user_id
                JOIN roles r ON r.id=uc.role_id
                WHERE uc.conference_id=?
                  AND r.code=?
                  AND u.email IS NOT NULL
                  AND u.email <> ''
                ORDER BY u.email
            ");
            $stmt->execute([(int)$conference['id'], $roleCode]);
            return $stmt->fetchAll(\PDO::FETCH_ASSOC);
        }

        if ($targetMode === 'all') {
            $stmt = $this->db()->prepare("
                SELECT DISTINCT 
                    u.id,
                    u.email,
                    CONCAT(COALESCE(u.first_name,''),' ',COALESCE(u.last_name,'')) AS full_name,
                    r.code AS role_code
                FROM user_conferences uc
                JOIN users u ON u.id=uc.user_id
                JOIN roles r ON r.id=uc.role_id
                WHERE uc.conference_id=?
                  AND u.email IS NOT NULL
                  AND u.email <> ''
                ORDER BY r.code, u.email
            ");
            $stmt->execute([(int)$conference['id']]);
            return $stmt->fetchAll(\PDO::FETCH_ASSOC);
        }

        return [];
    }

    public function index()
    {
        $this->requireAccess();
        $conference = $this->conference();
        $roles = $this->availableRoles();

        $stmt = $this->db()->prepare("
            SELECT 
                n.*,
                u.email,
                CONCAT(COALESCE(u.first_name,''),' ',COALESCE(u.last_name,'')) AS user_name
            FROM user_notifications n
            LEFT JOIN users u ON u.id=n.user_id
            WHERE n.conference_id=?
              AND n.org_id=?
              AND n.notification_type='broadcast'
            ORDER BY n.id DESC
            LIMIT 100
        ");
        $stmt->execute([(int)$conference['id'], (int)$conference['org_id']]);
        $recent = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        ob_start();
        require BASE_PATH . '/app/views/admin/notification_broadcast/index.php';
        $content = ob_get_clean();

        require BASE_PATH . '/app/views/layouts/admin_layout.php';
    }

    public function send()
    {
        $this->requireAccess();
        $conference = $this->conference();

        $targetMode = trim((string)($_POST['target_mode'] ?? 'role'));
        $roleCode = trim((string)($_POST['role_code'] ?? ''));
        $email = trim((string)($_POST['email'] ?? ''));

        $title = trim((string)($_POST['title'] ?? ''));
        $body = trim((string)($_POST['body'] ?? ''));
        $linkUrl = trim((string)($_POST['link_url'] ?? ''));

        if ($title === '') {
            $_SESSION['flash_error'] = "Notification title is required.";
            header("Location: /easychair/admin/notification-broadcast");
            exit;
        }

        if ($body === '') {
            $_SESSION['flash_error'] = "Notification body is required.";
            header("Location: /easychair/admin/notification-broadcast");
            exit;
        }

        if ($linkUrl !== '' && !str_starts_with($linkUrl, '/easychair/')) {
            $_SESSION['flash_error'] = "Link URL must start with /easychair/";
            header("Location: /easychair/admin/notification-broadcast");
            exit;
        }

        $recipients = $this->getRecipients($conference, $targetMode, $roleCode, $email);

        if (!$recipients) {
            $_SESSION['flash_error'] = "No recipients found for the selected target.";
            header("Location: /easychair/admin/notification-broadcast");
            exit;
        }

        $created = 0;
        $skipped = 0;
        $notifier = new NotificationService();

        foreach ($recipients as $u) {
            $nid = $notifier->create([
                'org_id' => (int)$conference['org_id'],
                'conference_id' => (int)$conference['id'],
                'user_id' => (int)$u['id'],
                'submission_id' => null,
                'notification_type' => 'broadcast',
                'event_key' => 'admin_broadcast',
                'title' => $title,
                'body' => $body,
                'link_url' => $linkUrl !== '' ? $linkUrl : null,
                'created_by' => (int)$_SESSION['user_id'],
            ]);

            if ($nid > 0) {
                $created++;
            } else {
                $skipped++;
            }
        }

        $_SESSION['flash_success'] = "Broadcast notification sent to {$created} user(s). Skipped by preferences: {$skipped}.";
        header("Location: /easychair/admin/notification-broadcast?sent=1");
        exit;
    }
}
