<?php
namespace App\Controllers;

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

use App\Core\Database;

class AdminOrgSmtpController
{
    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'], true)) {
            http_response_code(403);
            exit(function_exists('ec_t') ? ec_t('msg.access_denied', 'Access denied.') : '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(function_exists('ec_t') ? ec_t('msg.access_denied', 'Access denied.') : 'Access denied.');
        }

        return $c;
    }

    private function enc(?string $plain): ?string
    {
        $plain = (string)$plain;
        if ($plain === '') {
            return null;
        }

        return base64_encode($plain);
    }

    private function dec(?string $enc): string
    {
        $enc = (string)$enc;
        if ($enc === '') {
            return '';
        }

        $decoded = base64_decode($enc, true);
        return $decoded === false ? '' : $decoded;
    }

    private function settings(array $conference): ?array
    {
        $stmt = $this->db()->prepare("
            SELECT *
            FROM org_smtp_settings
            WHERE org_id = ?
              AND (conference_id = ? OR conference_id IS NULL)
            ORDER BY conference_id DESC, id DESC
            LIMIT 1
        ");
        $stmt->execute([(int)$conference['org_id'], (int)$conference['id']]);
        $row = $stmt->fetch(\PDO::FETCH_ASSOC);

        return $row ?: null;
    }

    public function index()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/org-smtp', 'view'); }
        $conference = $this->conference();
        $settings = $this->settings($conference);

        $smtpPasswordPreview = '';
        if (!empty($settings['smtp_password_enc'])) {
            $smtpPasswordPreview = '********';
        }

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

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

    public function save()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/org-smtp', 'update'); }
        $conference = $this->conference();

        $scope = (string)($_POST['scope'] ?? 'org');
        $conferenceId = $scope === 'conference' ? (int)$conference['id'] : null;

        $smtpHost = trim((string)($_POST['smtp_host'] ?? ''));
        $smtpPort = (int)($_POST['smtp_port'] ?? 587);
        $smtpUsername = trim((string)($_POST['smtp_username'] ?? ''));
        $smtpPassword = (string)($_POST['smtp_password'] ?? '');
        $smtpEncryption = trim((string)($_POST['smtp_encryption'] ?? 'tls'));
        $fromEmail = trim((string)($_POST['from_email'] ?? ''));
        $fromName = trim((string)($_POST['from_name'] ?? ''));
        $replyTo = trim((string)($_POST['reply_to'] ?? ''));
        $testRecipient = trim((string)($_POST['test_recipient'] ?? ''));

        if (!in_array($smtpEncryption, ['none','ssl','tls'], true)) {
            $smtpEncryption = 'tls';
        }

        if ($smtpHost === '') {
            $_SESSION['flash_error'] = 'SMTP host is required.';
            header("Location: /easychair/admin/org-smtp");
            exit;
        }

        $existing = null;
        $stmt = $this->db()->prepare("
            SELECT *
            FROM org_smtp_settings
            WHERE org_id = ?
              AND " . ($conferenceId === null ? "conference_id IS NULL" : "conference_id = ?") . "
            LIMIT 1
        ");

        if ($conferenceId === null) {
            $stmt->execute([(int)$conference['org_id']]);
        } else {
            $stmt->execute([(int)$conference['org_id'], $conferenceId]);
        }

        $existing = $stmt->fetch(\PDO::FETCH_ASSOC);

        $passwordEnc = $smtpPassword !== ''
            ? $this->enc($smtpPassword)
            : ($existing['smtp_password_enc'] ?? null);

        $stmt = $this->db()->prepare("
            INSERT INTO org_smtp_settings
            (org_id, conference_id, smtp_host, smtp_port, smtp_username, smtp_password_enc, smtp_encryption,
             from_email, from_name, reply_to, is_active, test_recipient, updated_by)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            ON DUPLICATE KEY UPDATE
                smtp_host=VALUES(smtp_host),
                smtp_port=VALUES(smtp_port),
                smtp_username=VALUES(smtp_username),
                smtp_password_enc=VALUES(smtp_password_enc),
                smtp_encryption=VALUES(smtp_encryption),
                from_email=VALUES(from_email),
                from_name=VALUES(from_name),
                reply_to=VALUES(reply_to),
                is_active=VALUES(is_active),
                test_recipient=VALUES(test_recipient),
                updated_by=VALUES(updated_by),
                updated_at=NOW()
        ");

        $stmt->execute([
            (int)$conference['org_id'],
            $conferenceId,
            $smtpHost,
            $smtpPort,
            $smtpUsername,
            $passwordEnc,
            $smtpEncryption,
            $fromEmail,
            $fromName,
            $replyTo,
            !empty($_POST['is_active']) ? 1 : 0,
            $testRecipient,
            (int)$_SESSION['user_id'],
        ]);

        $_SESSION['flash_success'] = 'SMTP settings saved.';
        header("Location: /easychair/admin/org-smtp");
        exit;
    }

    public function test()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/org-smtp', 'create'); }
        $conference = $this->conference();
        $settings = $this->settings($conference);

        if (!$settings) {
            $_SESSION['flash_error'] = 'Please save SMTP settings first.';
            header("Location: /easychair/admin/org-smtp");
            exit;
        }

        $to = trim((string)($_POST['test_recipient'] ?? $settings['test_recipient'] ?? ''));
        if ($to === '') {
            $_SESSION['flash_error'] = 'Test recipient is required.';
            header("Location: /easychair/admin/org-smtp");
            exit;
        }

        $subject = 'EasyChair SMTP Test - ' . ($conference['short_name'] ?? 'Conference');
        $body = "This is a test email from EasyChair organization SMTP settings.\n\nConference: " . ($conference['short_name'] ?? '');

        $status = 'queued';
        $error = null;

        try {
            $stmt = $this->db()->prepare("
                INSERT INTO conference_mail_outbox
                (org_id, conference_id, template_key, event_key, recipient_email, subject, body, status, created_at)
                VALUES (?, ?, 'smtp_test', 'smtp_test', ?, ?, ?, 'queued', NOW())
            ");
            $stmt->execute([
                (int)$conference['org_id'],
                (int)$conference['id'],
                $to,
                $subject,
                $body,
            ]);

            $status = 'queued';
        } catch (\Throwable $e) {
            $status = 'failed';
            $error = $e->getMessage();
        }

        $stmt = $this->db()->prepare("
            UPDATE org_smtp_settings
            SET last_test_status=?, last_test_error=?, last_test_at=NOW(), test_recipient=?
            WHERE id=?
        ");
        $stmt->execute([$status, $error, $to, (int)$settings['id']]);

        $_SESSION['flash_success'] = $status === 'queued'
            ? 'Test email queued. Run the mail worker to send it.'
            : 'Test email failed: ' . $error;

        header("Location: /easychair/admin/org-smtp");
        exit;
    }
}
