<?php
namespace App\Controllers;

use Core\Controller;
use App\Helpers\Helper;

class SettingsController extends Controller
{
    public function __construct()
    {
        parent::__construct();
        $this->requireRole(['super_admin']);
    }

    public function index(): void
    {
        $settings = $this->db->fetchAll("SELECT * FROM settings ORDER BY `group`, `key`");
        $grouped  = [];
        foreach ($settings as $s) {
            $grouped[$s['group']][$s['key']] = $s;
        }
        $this->adminView('settings.index', compact('grouped') + ['title'=>'System Settings']);
    }

    public function update(): void
    {
        $this->verifyCsrf();
        $settings = $_POST['settings'] ?? [];
        foreach ($settings as $key => $value) {
            $this->db->update('settings', ['value' => $value], '`key`=?', [$key]);
        }
        Helper::setFlash('success', 'Settings saved successfully.');
        $this->redirect(APP_URL . '/admin/settings');
    }

    public function testMail(): void
    {
        $this->verifyCsrf();
        $to = $this->input('test_email', '');
        if (!filter_var($to, FILTER_VALIDATE_EMAIL)) {
            $this->json(['success' => false, 'message' => 'Invalid email address.']);
            return;
        }

        // Load SMTP settings from DB
        $rows = $this->db->fetchAll("SELECT `key`, value FROM settings WHERE `group`='email'");
        $cfg  = [];
        foreach ($rows as $r) { $cfg[$r['key']] = $r['value']; }

        $host     = trim($cfg['smtp_host']         ?? '');
        $port     = (int)($cfg['smtp_port']         ?? 587);
        $user     = trim($cfg['smtp_username']      ?? '');
        $pass     = $cfg['smtp_password']            ?? '';
        $from     = trim($cfg['mail_from_address']   ?? $user);
        $fromName = trim($cfg['mail_from_name']      ?? 'Zabibu Residence');
        $enc      = strtolower(trim($cfg['smtp_encryption'] ?? ($port == 465 ? 'ssl' : 'tls')));

        if (!$host || !$user || !$pass) {
            $this->json(['success' => false, 'message' => 'SMTP host, username and password are required. Please fill in your Email / SMTP settings first.']);
            return;
        }

        $subject  = 'Test Email - ' . $fromName . ' SMTP Configuration';
        $date     = date('r');
        $msgId    = '<test.' . time() . '@' . str_replace('mail.', '', $host) . '>';
        $htmlBody = '<!DOCTYPE html><html><body style="font-family:Arial,sans-serif;color:#333;max-width:600px;margin:0 auto;padding:20px">'
            . '<div style="background:#1a3c5e;padding:20px;border-radius:8px 8px 0 0;text-align:center">'
            . '<h2 style="color:#fff;margin:0">' . htmlspecialchars($fromName) . '</h2></div>'
            . '<div style="background:#f9f9f9;padding:30px;border:1px solid #ddd;border-top:none;border-radius:0 0 8px 8px">'
            . '<h3 style="color:#1a3c5e">SMTP Test Successful</h3>'
            . '<p>This is a test email to confirm your SMTP configuration is working correctly.</p>'
            . '<table style="width:100%;border-collapse:collapse;margin:16px 0">'
            . '<tr style="background:#e8f0fe"><td style="padding:8px;font-weight:bold;width:40%">SMTP Host</td><td style="padding:8px">' . htmlspecialchars($host) . '</td></tr>'
            . '<tr><td style="padding:8px;font-weight:bold">SMTP Port</td><td style="padding:8px">' . $port . '</td></tr>'
            . '<tr style="background:#e8f0fe"><td style="padding:8px;font-weight:bold">Encryption</td><td style="padding:8px">' . strtoupper($enc) . '</td></tr>'
            . '<tr><td style="padding:8px;font-weight:bold">Sent From</td><td style="padding:8px">' . htmlspecialchars($from) . '</td></tr>'
            . '<tr style="background:#e8f0fe"><td style="padding:8px;font-weight:bold">Sent At</td><td style="padding:8px">' . $date . '</td></tr>'
            . '</table>'
            . '<p style="color:#666;font-size:13px">If you received this email, your email settings are configured properly.</p>'
            . '</div></body></html>';

        try {
            // SSL wrapping for port 465, plain socket for 587 (STARTTLS)
            $ctx = stream_context_create([
                'ssl' => [
                    'verify_peer'       => false,
                    'verify_peer_name'  => false,
                    'allow_self_signed' => true,
                ]
            ]);

            $socketAddr = ($enc === 'ssl' ? 'ssl://' : '') . $host . ':' . $port;
            $sock = @stream_socket_client($socketAddr, $errno, $errstr, 15, STREAM_CLIENT_CONNECT, $ctx);
            if (!$sock) {
                throw new \Exception("Cannot connect to {$host}:{$port} — {$errstr} ({$errno}). Check host/port and firewall.");
            }
            stream_set_timeout($sock, 15);

            $recv = function(string $expect = '') use ($sock): string {
                $resp = '';
                while ($line = fgets($sock, 515)) {
                    $resp .= $line;
                    if (substr($line, 3, 1) === ' ') break;
                }
                if ($expect && substr(trim($resp), 0, strlen($expect)) !== $expect) {
                    throw new \Exception("Expected {$expect}, got: " . trim($resp));
                }
                return $resp;
            };
            $send = function(string $cmd) use ($sock): void {
                fwrite($sock, $cmd . "\r\n");
            };

            $recv('220'); // greeting
            $send('EHLO ' . (gethostname() ?: 'localhost'));
            $recv('250');

            if ($enc === 'tls') {
                $send('STARTTLS');
                $recv('220');
                stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
                $send('EHLO ' . (gethostname() ?: 'localhost'));
                $recv('250');
            }

            $send('AUTH LOGIN');
            $recv('334');
            $send(base64_encode($user));
            $recv('334');
            $send(base64_encode($pass));
            $authResp = $recv();
            if (substr(trim($authResp), 0, 3) !== '235') {
                throw new \Exception("Authentication failed. Check username/password. Server said: " . trim($authResp));
            }

            $send("MAIL FROM:<{$from}>");
            $recv('250');
            $send("RCPT TO:<{$to}>");
            $rcptResp = $recv();
            if (substr(trim($rcptResp), 0, 3) !== '250') {
                throw new \Exception("Recipient rejected: " . trim($rcptResp));
            }
            $send('DATA');
            $recv('354');
            $boundary = 'boundary_' . md5(time());
            $plainBody = "Hello,\r\n\r\nThis is a test email from {$fromName}.\r\nYour SMTP configuration is working correctly.\r\n\r\nSMTP Host: {$host}:{$port} ({$enc})\r\nSent: {$date}\r\n\r\n-- {$fromName}";
            $send(
                "Date: {$date}\r\n" .
                "Message-ID: {$msgId}\r\n" .
                "From: {$fromName} <{$from}>\r\n" .
                "Reply-To: {$from}\r\n" .
                "To: {$to}\r\n" .
                "Subject: {$subject}\r\n" .
                "MIME-Version: 1.0\r\n" .
                "Content-Type: multipart/alternative; boundary=\"{$boundary}\"\r\n" .
                "X-Mailer: Zabibu-Residence-Mailer\r\n" .
                "\r\n" .
                "--{$boundary}\r\n" .
                "Content-Type: text/plain; charset=UTF-8\r\n" .
                "Content-Transfer-Encoding: base64\r\n\r\n" .
                chunk_split(base64_encode($plainBody)) .
                "--{$boundary}\r\n" .
                "Content-Type: text/html; charset=UTF-8\r\n" .
                "Content-Transfer-Encoding: base64\r\n\r\n" .
                chunk_split(base64_encode($htmlBody)) .
                "--{$boundary}--\r\n."
            );
            $dataResp = $recv();
            $send('QUIT');
            fclose($sock);

            if (substr(trim($dataResp), 0, 3) !== '250') {
                throw new \Exception("Message rejected by server: " . trim($dataResp));
            }

            $this->json(['success' => true, 'message' => "✓ Test email sent successfully to {$to} via {$host}:{$port}."]);
        } catch (\Exception $e) {
            $this->json(['success' => false, 'message' => $e->getMessage()]);
        }
    }

    public function uploadLogo(): void
    {
        $this->verifyCsrf();
        if (!empty($_FILES['logo']['name'])) {
            $path = Helper::uploadFile($_FILES['logo'], 'logos', ALLOWED_IMAGE_TYPES);
            if ($path) {
                $this->db->update('settings', ['value' => $path], '`key`=?', ['company_logo']);
                Helper::setFlash('success', 'Logo updated.');
            } else {
                Helper::setFlash('danger', 'Failed to upload logo.');
            }
        }
        $this->redirect(APP_URL . '/admin/settings');
    }

    public function uploadImage(): void
    {
        $this->verifyCsrf();
        $key = $this->input('image_key', '');
        $allowedKeys = ['hero_image', 'hero_bg_image', 'about_image'];

        if (!in_array($key, $allowedKeys)) {
            Helper::setFlash('danger', 'Invalid image key.');
            $this->redirect(APP_URL . '/admin/settings?tab=content');
            return;
        }

        if (empty($_FILES['image_file']['tmp_name'])) {
            Helper::setFlash('danger', 'No file selected.');
            $this->redirect(APP_URL . '/admin/settings?tab=content');
            return;
        }

        $file    = $_FILES['image_file'];
        $allowed = ['image/jpeg', 'image/png', 'image/webp'];
        $maxSize = 5 * 1024 * 1024;

        if (!in_array($file['type'], $allowed)) {
            Helper::setFlash('danger', 'Invalid file type. Use JPG, PNG or WebP.');
            $this->redirect(APP_URL . '/admin/settings?tab=content');
            return;
        }
        if ($file['size'] > $maxSize) {
            Helper::setFlash('danger', 'File too large. Maximum size is 5MB.');
            $this->redirect(APP_URL . '/admin/settings?tab=content');
            return;
        }

        $dir = APP_ROOT . '/public/assets/images/site/';
        if (!is_dir($dir)) {
            mkdir($dir, 0755, true);
        }

        $ext      = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        $filename = $key . '_' . time() . '.' . $ext;
        $dest     = $dir . $filename;

        if (!move_uploaded_file($file['tmp_name'], $dest)) {
            Helper::setFlash('danger', 'Failed to save image. Check folder permissions.');
            $this->redirect(APP_URL . '/admin/settings?tab=content');
            return;
        }

        $storedPath = 'site/' . $filename;

        $existing = $this->db->fetch("SELECT id FROM settings WHERE `key`=?", [$key]);
        if ($existing) {
            $this->db->update('settings', ['value' => $storedPath], '`key`=?', [$key]);
        } else {
            $this->db->query("INSERT INTO settings (`group`, `key`, `value`, `label`) VALUES (?, ?, ?, ?)", ['content', $key, $storedPath, $key]);
        }

        Helper::setFlash('success', 'Image uploaded successfully.');
        $this->redirect(APP_URL . '/admin/settings?tab=content');
    }

    public function removeImage(): void
    {
        $this->verifyCsrf();
        $key = $this->input('image_key', '');
        $allowedKeys = ['hero_image', 'hero_bg_image', 'about_image'];

        if (!in_array($key, $allowedKeys)) {
            Helper::setFlash('danger', 'Invalid image key.');
            $this->redirect(APP_URL . '/admin/settings?tab=content');
            return;
        }

        $existing = $this->db->fetch("SELECT value FROM settings WHERE `key`=?", [$key]);
        if ($existing && !empty($existing['value'])) {
            $filePath = APP_ROOT . '/public/assets/images/' . $existing['value'];
            if (is_file($filePath)) {
                @unlink($filePath);
            }
        }

        $this->db->update('settings', ['value' => ''], '`key`=?', [$key]);
        Helper::setFlash('success', 'Photo removed. The site will now use the default image.');
        $this->redirect(APP_URL . '/admin/settings?tab=content');
    }
}
