<?php
namespace App\Controllers;

require_once BASE_PATH . '/app/helpers/permissions.php';

require_once BASE_PATH . '/app/helpers/conference_scope.php';

use App\Core\Database;
use App\Core\SmtpMailer;

class AdminConferenceMailController
{
    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(), ['superadmin','org_admin','admin','organizer','conference_chair'], true)) {
            http_response_code(403);
            exit("Access denied.");
        }
    }

    private function conference(): array
    {
        $stmt = $this->db()->prepare("SELECT * FROM conferences WHERE id=? LIMIT 1");
        $stmt->execute([(int)$_SESSION['conference_id']]);
        $c = $stmt->fetch(\PDO::FETCH_ASSOC);

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

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

        return $c;
    }

    private function mailRow(int $id, array $conference): array
    {
        $stmt = $this->db()->prepare("
            SELECT *
            FROM conference_mail_outbox
            WHERE id=?
              AND conference_id=?
              AND org_id=?
            LIMIT 1
        ");
        $stmt->execute([$id, (int)$conference['id'], (int)$conference['org_id']]);
        $m = $stmt->fetch(\PDO::FETCH_ASSOC);

        if (!$m) {
            exit("Mail row not found.");
        }

        return $m;
    }

    private function logSubmissionActivity(array $mail, string $eventKey, string $title, string $body): void
    {
        if (empty($mail['submission_id'])) {
            return;
        }

        $stmt = $this->db()->prepare("
            INSERT INTO submission_activity_log
            (org_id, conference_id, submission_id, actor_id, actor_role, event_key, event_title, event_body)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?)
        ");
        $stmt->execute([
            (int)$mail['org_id'],
            (int)$mail['conference_id'],
            (int)$mail['submission_id'],
            (int)($_SESSION['user_id'] ?? 0),
            $this->role(),
            $eventKey,
            $title,
            $body
        ]);
    }

    private function sendOne(array $mail): array
    {
        if (empty($mail['recipient_email'])) {
            return ['ok' => false, 'error' => 'Recipient email is missing.'];
        }

        if (empty($mail['subject']) || empty($mail['body'])) {
            return ['ok' => false, 'error' => 'Subject or body is missing.'];
        }

        $attempt = $this->db()->prepare("
            UPDATE conference_mail_outbox
            SET retry_count=COALESCE(retry_count,0)+1,
                last_attempt_at=NOW()
            WHERE id=?
        ");
        $attempt->execute([(int)$mail['id']]);

        $mailer = new SmtpMailer();
        $result = $mailer->send(
            (string)$mail['recipient_email'],
            (string)$mail['subject'],
            (string)$mail['body'],
            (string)($mail['recipient_name'] ?: $mail['recipient_email'])
        );

        if (!empty($result['ok'])) {
            $stmt = $this->db()->prepare("
                UPDATE conference_mail_outbox
                SET status='sent',
                    sent_at=NOW(),
                    error_message=NULL
                WHERE id=?
            ");
            $stmt->execute([(int)$mail['id']]);

            $this->logSubmissionActivity(
                $mail,
                'email_resent',
                'Conference email sent',
                'Outbox ID: ' . (int)$mail['id'] . "\nTemplate: " . ($mail['template_key'] ?? '')
            );

            return ['ok' => true, 'error' => null];
        }

        $error = trim(($result['error'] ?? 'SMTP failed') . "\n\n" . ($result['debug'] ?? ''));

        $stmt = $this->db()->prepare("
            UPDATE conference_mail_outbox
            SET status='failed',
                error_message=?
            WHERE id=?
        ");
        $stmt->execute([$error, (int)$mail['id']]);

        $this->logSubmissionActivity(
            $mail,
            'email_failed',
            'Conference email failed',
            'Outbox ID: ' . (int)$mail['id'] . "\nError: " . $error
        );

        return ['ok' => false, 'error' => $error];
    }

    public function index()
    {

        // Pack512: non-superadmin bypasses selector safely.
        if (function_exists('ec_scope_role') && ec_scope_role() !== 'superadmin') {
            if (function_exists('ec_scope_auto_select_conference')) {
                // ec_scope_auto_select_conference(true);
            }
            $landing = function_exists('ec_scope_landing_url') ? ec_scope_landing_url() : '/easychair/admin/dashboard';
            header("Location: " . $landing);
            exit;
        }

$this->requireAccess();
        $conference = $this->conference();

        $status = trim((string)($_GET['status'] ?? ''));
        $q = trim((string)($_GET['q'] ?? ''));

        $where = "
            WHERE m.conference_id=?
              AND m.org_id=?
        ";
        $params = [(int)$conference['id'], (int)$conference['org_id']];

        if ($status !== '') {
            $where .= " AND m.status=? ";
            $params[] = $status;
        }

        if ($q !== '') {
            $where .= " AND (
                m.recipient_email LIKE ?
                OR m.subject LIKE ?
                OR m.template_key LIKE ?
                OR m.event_key LIKE ?
                OR s.submission_no LIKE ?
            ) ";
            $like = '%' . $q . '%';
            array_push($params, $like, $like, $like, $like, $like);
        }

        $stmt = $this->db()->prepare("
            SELECT 
                m.*,
                s.submission_no,
                COALESCE(s.title,s.title_en,s.title_ar) AS submission_title
            FROM conference_mail_outbox m
            LEFT JOIN submissions s ON s.id=m.submission_id
            {$where}
            ORDER BY m.id DESC
            LIMIT 300
        ");
        $stmt->execute($params);
        $mails = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $stmt = $this->db()->prepare("
            SELECT status, COUNT(*) AS total
            FROM conference_mail_outbox
            WHERE conference_id=?
              AND org_id=?
            GROUP BY status
        ");
        $stmt->execute([(int)$conference['id'], (int)$conference['org_id']]);
        $stats = $stmt->fetchAll(\PDO::FETCH_KEY_PAIR);

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

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

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

        $mail = $this->mailRow((int)($_GET['id'] ?? 0), $conference);
        $result = $this->sendOne($mail);

        $_SESSION['mail_flash'] = !empty($result['ok'])
            ? 'Email sent successfully.'
            : 'Email failed: ' . mb_substr((string)$result['error'], 0, 500);

        header("Location: /easychair/admin/conference-mail");
        exit;
    }

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

        $stmt = $this->db()->prepare("
            SELECT *
            FROM conference_mail_outbox
            WHERE conference_id=?
              AND org_id=?
              AND status IN ('queued','failed')
            ORDER BY id ASC
            LIMIT 50
        ");
        $stmt->execute([(int)$conference['id'], (int)$conference['org_id']]);
        $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $sent = 0;
        $failed = 0;

        foreach ($rows as $row) {
            $result = $this->sendOne($row);
            if (!empty($result['ok'])) {
                $sent++;
            } else {
                $failed++;
            }
        }

        $_SESSION['mail_flash'] = "Queue processed. Sent: {$sent}, Failed: {$failed}.";
        header("Location: /easychair/admin/conference-mail");
        exit;
    }

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

        $id = (int)($_GET['id'] ?? 0);

        $stmt = $this->db()->prepare("
            UPDATE conference_mail_outbox
            SET status='cancelled',
                error_message='Cancelled by admin'
            WHERE id=?
              AND conference_id=?
              AND org_id=?
              AND status IN ('queued','failed')
        ");
        $stmt->execute([$id, (int)$conference['id'], (int)$conference['org_id']]);

        $_SESSION['mail_flash'] = "Email cancelled.";
        header("Location: /easychair/admin/conference-mail");
        exit;
    }

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

        $mail = $this->mailRow((int)($_GET['id'] ?? 0), $conference);

        header('Content-Type: text/plain; charset=UTF-8');
        echo "To: " . ($mail['recipient_email'] ?? '') . "\n";
        echo "Subject: " . ($mail['subject'] ?? '') . "\n";
        echo "Status: " . ($mail['status'] ?? '') . "\n";
        echo "Created: " . ($mail['created_at'] ?? '') . "\n";
        echo "Sent: " . ($mail['sent_at'] ?? '') . "\n";
        echo "\n---------------- BODY ----------------\n\n";
        echo (string)($mail['body'] ?? '');
        echo "\n\n---------------- ERROR ----------------\n\n";
        echo (string)($mail['error_message'] ?? '');
        exit;
    }
}
