<?php

declare(strict_types=1);

namespace SuperAdmin\Controllers;

use App\Core\Controller;

/**
 * Super Admin Base Controller
 *
 * Abstract base for all Super Admin panel controllers.
 *
 * The Super Admin panel is SEPARATE from the existing /admin/* panel:
 *   - /admin/*         → manages website frontage (sliders, courses display, gallery, blog)
 *   - /super-admin/*   → manages branches, branch admins, certificate templates, etc.
 *
 * Both panels share the same `users` table but use different role checks:
 *   - admin/*          requires role='admin'
 *   - super-admin/*    requires role='super_admin'
 */
abstract class SuperAdminBaseController extends Controller
{
    /** Base path for Super Admin view files */
    private const VIEW_PATH = APP_ROOT . '/super-admin/Views/';

    /**
     * Render a Super Admin view wrapped in the Super Admin layout.
     *
     * Auto-injects: csrfToken, currentUser, flash messages, title, currentPage,
     * unreadCounts (chat + pending applications + pending testimonials).
     *
     * @param string $view View path relative to /super-admin/Views/ (e.g. 'dashboard', 'branches/index')
     * @param array<string, mixed> $data Data to extract into the view
     * @return never
     */
    protected function superAdminView(string $view, array $data = []): never
    {
        extract($data, EXTR_SKIP);

        // Flash messages
        $flash_error   = flash('error');
        $flash_success = flash('success');
        $flash_warning = flash('warning');
        $flash_info    = flash('info');

        // CSRF token
        $csrfToken = generateCsrfToken();

        // Current user (from session)
        $currentUser = getCurrentUser();

        // Default page title
        $title       = $title ?? 'Super Admin';
        $currentPage = $currentPage ?? '';

        // Pending counts for sidebar badges (best-effort — wrapped in try-catch)
        $pendingApplications = 0;
        $pendingTestimonials = 0;
        try {
            $stmt = $this->db->query("SELECT COUNT(*) AS cnt FROM `branch_applications` WHERE `status` = 'pending'");
            $pendingApplications = (int) ($stmt->fetch()['cnt'] ?? 0);
        } catch (\Throwable $e) { /* ignore */ }

        try {
            $stmt = $this->db->query("SELECT COUNT(*) AS cnt FROM `testimonials` WHERE `status` = 'pending'");
            $pendingTestimonials = (int) ($stmt->fetch()['cnt'] ?? 0);
        } catch (\Throwable $e) { /* ignore */ }

        // Build full path to view file
        $viewFile = self::VIEW_PATH . $view . '.php';
        if (!file_exists($viewFile)) {
            http_response_code(500);
            error_log("Super Admin view not found: {$viewFile}");
            echo "Error: Super Admin view '{$view}' could not be found.";
            exit;
        }

        // Capture view content
        ob_start();
        require $viewFile;
        $content = ob_get_clean();

        // Render layout
        $layoutFile = self::VIEW_PATH . 'layout.php';
        if (!file_exists($layoutFile)) {
            // Fallback: output content without layout
            echo $content;
            exit;
        }

        require $layoutFile;
        exit;
    }

    /**
     * Render the Super Admin login view (NOT wrapped in layout).
     */
    protected function loginView(array $data = []): never
    {
        extract($data, EXTR_SKIP);

        $flash_error   = flash('error');
        $flash_success = flash('success');
        $csrfToken     = generateCsrfToken();
        $title         = $title ?? 'Super Admin Login';

        $viewFile = self::VIEW_PATH . 'auth/login.php';
        if (!file_exists($viewFile)) {
            http_response_code(500);
            echo 'Error: Super Admin login view could not be found.';
            exit;
        }

        require $viewFile;
        exit;
    }

    /**
     * Handle image upload with validation.
     * (Same logic as AdminController::handleImageUpload but in SuperAdmin namespace.)
     */
    protected function handleImageUpload(string $fieldName, string $subDir = ''): ?string
    {
        if (!isset($_FILES[$fieldName]) || $_FILES[$fieldName]['error'] !== UPLOAD_ERR_OK) {
            return null;
        }

        $file = $_FILES[$fieldName];

        if ($file['size'] > 5 * 1024 * 1024) {
            flash('error', 'Image size must be less than 5MB.');
            return null;
        }

        $allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mimeType = finfo_file($finfo, $file['tmp_name']);
        finfo_close($finfo);

        if (!in_array($mimeType, $allowedTypes, true)) {
            flash('error', 'Only JPG, PNG, GIF, and WebP images are allowed.');
            return null;
        }

        $extension = pathinfo($file['name'], PATHINFO_EXTENSION);
        $filename = uniqid('img_', true) . '.' . $extension;
        $uploadDir = PUBLIC_ROOT . '/uploads/' . $subDir;

        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0777, true);
        }

        if (!is_writable($uploadDir)) {
            @chmod($uploadDir, 0777);
            if (!is_writable($uploadDir)) {
                flash('error', 'Upload directory is not writable.');
                return null;
            }
        }

        $destination = $uploadDir . '/' . $filename;
        if (!move_uploaded_file($file['tmp_name'], $destination)) {
            flash('error', 'Failed to upload image.');
            return null;
        }

        @chmod($destination, 0644);
        return 'uploads/' . ($subDir ? $subDir . '/' : '') . $filename;
    }

    /**
     * Check if a column exists in a database table (safely).
     */
    protected function columnExists(string $table, string $column): bool
    {
        try {
            $stmt = $this->db->prepare(
                "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
                 WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = :table AND COLUMN_NAME = :column"
            );
            $stmt->execute([':table' => $table, ':column' => $column]);
            return (int) $stmt->fetchColumn() > 0;
        } catch (\Throwable $e) {
            return false;
        }
    }

    /**
     * Write an entry to the audit log.
     */
    protected function auditLog(string $action, string $entityType = '', ?int $entityId = null, ?string $details = null): void
    {
        try {
            $stmt = $this->db->prepare(
                'INSERT INTO `audit_log` (`user_id`, `branch_id`, `action`, `entity_type`, `entity_id`, `details`, `ip_address`, `created_at`)
                 VALUES (:uid, NULL, :action, :etype, :eid, :details, :ip, NOW())'
            );
            $stmt->execute([
                ':uid'      => $_SESSION['user_id'] ?? null,
                ':action'   => $action,
                ':etype'    => $entityType ?: null,
                ':eid'      => $entityId,
                ':details'  => $details,
                ':ip'       => $_SERVER['REMOTE_ADDR'] ?? null,
            ]);
        } catch (\Throwable $e) {
            error_log('Audit log write failed: ' . $e->getMessage());
        }
    }
}
