<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Core\Controller;

/**
 * Demo Class Controller
 *
 * Handles the demo class booking form on the homepage.
 * The form is embedded in the homepage and submits via POST.
 * Auto-creates or repairs the database table if needed.
 */
class DemoClassController extends Controller
{
    /**
     * Required columns for the demo_class_requests table.
     * Used by ensureTableExists() to detect and fix missing columns.
     */
    private const TABLE_COLUMNS = [
        'id'           => 'INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY',
        'student_name' => 'VARCHAR(255) NOT NULL',
        'email'        => 'VARCHAR(255) NOT NULL',
        'contact'      => 'VARCHAR(20) NOT NULL',
        'batch'        => 'VARCHAR(100) DEFAULT NULL',
        'course_id'    => 'INT UNSIGNED DEFAULT NULL',
        'demo_date'    => 'DATE NOT NULL',
        'status'       => "ENUM('pending','contacted','scheduled','completed','cancelled') NOT NULL DEFAULT 'pending'",
        'admin_note'   => 'TEXT DEFAULT NULL',
        'is_read'      => 'TINYINT(1) NOT NULL DEFAULT 0',
        'created_at'   => 'TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP',
        'updated_at'   => 'TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP',
    ];

    /**
     * Full CREATE TABLE SQL for the demo_class_requests table.
     */
    private const CREATE_TABLE_SQL = "
        CREATE TABLE IF NOT EXISTS `demo_class_requests` (
            `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
            `student_name` VARCHAR(255) NOT NULL,
            `email` VARCHAR(255) NOT NULL,
            `contact` VARCHAR(20) NOT NULL,
            `batch` VARCHAR(100) DEFAULT NULL,
            `course_id` INT UNSIGNED DEFAULT NULL,
            `demo_date` DATE NOT NULL,
            `status` ENUM('pending','contacted','scheduled','completed','cancelled') NOT NULL DEFAULT 'pending',
            `admin_note` TEXT DEFAULT NULL,
            `is_read` TINYINT(1) NOT NULL DEFAULT 0,
            `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
            `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            PRIMARY KEY (`id`),
            KEY `idx_status` (`status`),
            KEY `idx_is_read` (`is_read`),
            KEY `idx_demo_date` (`demo_date`),
            KEY `idx_course_id` (`course_id`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
    ";

    /**
     * Ensure the demo_class_requests table exists with ALL required columns.
     *
     * Strategy: Check existing columns. If ANY are missing → DROP and RECREATE
     * the entire table. This is the most reliable fix because ALTER TABLE ADD COLUMN
     * can fail with NOT NULL constraints on tables with existing rows, and the table
     * has never had a successful INSERT anyway (since columns were missing).
     *
     * @return void
     */
    private function ensureTableExists(): void
    {
        try {
            $stmt = $this->db->query('SHOW COLUMNS FROM `demo_class_requests`');
            $existingCols = array_column($stmt->fetchAll(\PDO::FETCH_ASSOC), 'Field');

            // Check if any required columns are missing
            $requiredCols = array_keys(self::TABLE_COLUMNS);
            $missingCols = array_diff($requiredCols, $existingCols);

            if (!empty($missingCols)) {
                // Table exists but is INCOMPLETE — drop and recreate
                error_log('Demo class: Table incomplete, missing columns: ' . implode(', ', $missingCols) . ' — dropping and recreating');
                $this->db->exec('DROP TABLE IF EXISTS `demo_class_requests`');
                $this->db->exec(self::CREATE_TABLE_SQL);
                error_log('Demo class: Table recreated successfully with all columns');
            }
        } catch (\Throwable $e) {
            // Table doesn't exist at all — create it fresh
            error_log('Demo class: Table does not exist, creating: ' . $e->getMessage());
            $this->db->exec(self::CREATE_TABLE_SQL);
            error_log('Demo class: Table created successfully');
        }
    }

    /**
     * Store a new demo class request.
     *
     * Validates form data and saves to the database.
     * Redirects back to homepage with success/error flash message.
     *
     * @return void
     */
    public function store(): void
    {
        $this->validateCsrf();

        $studentName = sanitize($_POST['student_name'] ?? '');
        $email       = sanitize($_POST['email'] ?? '');
        $contact     = sanitize($_POST['contact'] ?? '');
        $batch       = sanitize($_POST['batch'] ?? '');
        $courseId    = (int) ($_POST['course_id'] ?? 0);
        $demoDate    = sanitize($_POST['demo_date'] ?? '');

        // Validation
        $errors = [];

        if (empty($studentName) || mb_strlen($studentName) < 2) {
            $errors[] = 'Student name is required (minimum 2 characters).';
        }

        if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $errors[] = 'A valid email address is required.';
        }

        if (empty($contact) || !preg_match('/^[\d\s\+\-\(\)]{7,15}$/', $contact)) {
            $errors[] = 'A valid contact number is required (7-15 digits).';
        }

        if (empty($demoDate)) {
            $errors[] = 'Demo date is required.';
        } else {
            // Demo date must be today or in the future
            $today = date('Y-m-d');
            if ($demoDate < $today) {
                $errors[] = 'Demo date cannot be in the past.';
            }
        }

        if (!empty($errors)) {
            flash('error', implode(' ', $errors));
            redirect(BASE_PATH . '/');
        }

        // Ensure the table exists and has ALL required columns
        try {
            $this->ensureTableExists();
        } catch (\Throwable $e) {
            error_log('Demo class: ensureTableExists failed: ' . $e->getMessage());
        }

        // Insert into database
        try {
            $stmt = $this->db->prepare(
                'INSERT INTO `demo_class_requests` 
                    (`student_name`, `email`, `contact`, `batch`, `course_id`, `demo_date`, `status`, `is_read`) 
                 VALUES 
                    (:student_name, :email, :contact, :batch, :course_id, :demo_date, :status, :is_read)'
            );

            $stmt->execute([
                ':student_name' => $studentName,
                ':email'        => $email,
                ':contact'      => $contact,
                ':batch'        => $batch,
                ':course_id'    => $courseId > 0 ? $courseId : null,
                ':demo_date'    => $demoDate,
                ':status'       => 'pending',
                ':is_read'      => 0,
            ]);

            flash('success', 'Your demo class request has been submitted successfully! We will contact you soon.');

            // Send instant email notification to admin
            $this->sendAdminNotification($studentName, $email, $contact, $batch, $courseId, $demoDate);

        } catch (\Throwable $e) {
            error_log('Demo class request error: ' . $e->getMessage());

            // Last-resort: try dropping and recreating table, then retry INSERT once
            try {
                error_log('Demo class: Attempting emergency table rebuild...');
                $this->db->exec('DROP TABLE IF EXISTS `demo_class_requests`');
                $this->db->exec(self::CREATE_TABLE_SQL);

                $stmt = $this->db->prepare(
                    'INSERT INTO `demo_class_requests` 
                        (`student_name`, `email`, `contact`, `batch`, `course_id`, `demo_date`, `status`, `is_read`) 
                     VALUES 
                        (:student_name, :email, :contact, :batch, :course_id, :demo_date, :status, :is_read)'
                );

                $stmt->execute([
                    ':student_name' => $studentName,
                    ':email'        => $email,
                    ':contact'      => $contact,
                    ':batch'        => $batch,
                    ':course_id'    => $courseId > 0 ? $courseId : null,
                    ':demo_date'    => $demoDate,
                    ':status'       => 'pending',
                    ':is_read'      => 0,
                ]);

                flash('success', 'Your demo class request has been submitted successfully! We will contact you soon.');

                // Send instant email notification to admin
                $this->sendAdminNotification($studentName, $email, $contact, $batch, $courseId, $demoDate);

            } catch (\Throwable $e2) {
                error_log('Demo class: Emergency rebuild also failed: ' . $e2->getMessage());
                flash('error', 'Something went wrong. Please try again later.');
            }
        }

        redirect(BASE_PATH . '/');
    }

    /**
     * Send instant email notification to admin when a demo class enquiry is submitted.
     *
     * Uses the App\Core\Mail helper (PHPMailer wrapper) to send a formatted
     * HTML email to gmindinstitues@gmail.com with all the enquiry details.
     * If Mail/PHPMailer is not configured, the enquiry still saves — email is best-effort.
     *
     * @param string $name    Student name
     * @param string $email   Student email
     * @param string $contact Student phone
     * @param string $batch   Preferred batch timing
     * @param int    $courseId Course ID (0 if none selected)
     * @param string $demoDate Requested demo date
     */
    private function sendAdminNotification(string $name, string $email, string $contact, string $batch, int $courseId, string $demoDate): void
    {
        $logFile = dirname(__DIR__, 2) . '/logs/email_debug.log';
        $logDir = dirname($logFile);
        if (!is_dir($logDir)) {
            @mkdir($logDir, 0755, true);
        }

        $log = function (string $msg) use ($logFile): void {
            $ts = date('Y-m-d H:i:s');
            @file_put_contents($logFile, "[{$ts}] {$msg}\n", FILE_APPEND);
            error_log('Demo class email: ' . $msg);
        };

        try {
            $log('Starting email notification for enquiry from ' . $name);

            // Try to get course name if course was selected
            $courseName = 'Not specified';
            if ($courseId > 0) {
                try {
                    $courseModel = $this->model('Course');
                    $course = $courseModel->find($courseId);
                    if ($course) {
                        $courseName = $course['name'] ?? 'Unknown Course';
                    }
                } catch (\Throwable $e) {
                    // Ignore — use default
                }
            }

            $adminEmail = 'gmindinstitues@gmail.com';
            $subject = 'New Demo Class Enquiry - ' . $name;

            $htmlBody = '
            <div style="font-family: Arial, Helvetica, sans-serif; max-width: 600px; margin: 0 auto; background: #f4f7fc; padding: 20px;">
                <div style="background: #ffffff; border-radius: 12px; padding: 30px; box-shadow: 0 2px 12px rgba(0,0,0,0.08);">
                    <div style="text-align: center; margin-bottom: 24px; padding-bottom: 16px; border-bottom: 3px solid #4A6CF7;">
                        <h1 style="margin: 0; color: #0d2b6e; font-size: 22px;">New Demo Class Enquiry</h1>
                        <p style="margin: 6px 0 0; color: #888; font-size: 13px;">Gmind Institute — ' . date('d M Y, h:i A') . '</p>
                    </div>

                    <table style="width: 100%; border-collapse: collapse; font-size: 14px;">
                        <tr>
                            <td style="padding: 10px 12px; border-bottom: 1px solid #eee; color: #666; font-weight: 600; width: 140px;">Student Name</td>
                            <td style="padding: 10px 12px; border-bottom: 1px solid #eee; color: #333;">' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</td>
                        </tr>
                        <tr>
                            <td style="padding: 10px 12px; border-bottom: 1px solid #eee; color: #666; font-weight: 600;">Email</td>
                            <td style="padding: 10px 12px; border-bottom: 1px solid #eee; color: #333;">
                                <a href="mailto:' . htmlspecialchars($email, ENT_QUOTES, 'UTF-8') . '" style="color: #4A6CF7;">' . htmlspecialchars($email, ENT_QUOTES, 'UTF-8') . '</a>
                            </td>
                        </tr>
                        <tr>
                            <td style="padding: 10px 12px; border-bottom: 1px solid #eee; color: #666; font-weight: 600;">Contact Number</td>
                            <td style="padding: 10px 12px; border-bottom: 1px solid #eee; color: #333;">
                                <a href="tel:' . htmlspecialchars($contact, ENT_QUOTES, 'UTF-8') . '" style="color: #4A6CF7;">' . htmlspecialchars($contact, ENT_QUOTES, 'UTF-8') . '</a>
                            </td>
                        </tr>
                        <tr>
                            <td style="padding: 10px 12px; border-bottom: 1px solid #eee; color: #666; font-weight: 600;">Preferred Batch</td>
                            <td style="padding: 10px 12px; border-bottom: 1px solid #eee; color: #333;">' . htmlspecialchars($batch ?: 'Not specified', ENT_QUOTES, 'UTF-8') . '</td>
                        </tr>
                        <tr>
                            <td style="padding: 10px 12px; border-bottom: 1px solid #eee; color: #666; font-weight: 600;">Course Interest</td>
                            <td style="padding: 10px 12px; border-bottom: 1px solid #eee; color: #333;">' . htmlspecialchars($courseName, ENT_QUOTES, 'UTF-8') . '</td>
                        </tr>
                        <tr>
                            <td style="padding: 10px 12px; color: #666; font-weight: 600;">Demo Date</td>
                            <td style="padding: 10px 12px; color: #e84118; font-weight: 700;">' . date('d F Y', strtotime($demoDate)) . '</td>
                        </tr>
                    </table>

                    <div style="margin-top: 24px; text-align: center;">
                        <a href="' . BASE_PATH . '/admin/demo-class" style="display: inline-block; padding: 12px 32px; background: linear-gradient(135deg, #4A6CF7, #6C3FE8); color: #fff; text-decoration: none; border-radius: 8px; font-weight: 600; font-size: 14px;">
                            View in Admin Panel
                        </a>
                    </div>
                </div>
                <p style="text-align: center; color: #aaa; font-size: 11px; margin-top: 16px;">
                    This is an automated notification from Gmind Institute website.
                </p>
            </div>';

            $textBody = "New Demo Class Enquiry\n"
                      . "========================\n"
                      . "Student Name: {$name}\n"
                      . "Email: {$email}\n"
                      . "Contact: {$contact}\n"
                      . "Preferred Batch: " . ($batch ?: 'Not specified') . "\n"
                      . "Course Interest: {$courseName}\n"
                      . "Demo Date: {$demoDate}\n"
                      . "Time: " . date('d M Y, h:i A') . "\n\n"
                      . "View in Admin: " . BASE_PATH . "/admin/demo-class";

            // === Strategy 1: Use App\Core\Mail (PHPMailer wrapper) ===
            try {
                $mail = new \App\Core\Mail();

                // Log mail status for debugging
                $status = $mail->getStatus();
                $log('Strategy 1: Mail status = ' . json_encode($status));

                if ($mail->isAvailable() && $mail->isConfigured()) {
                    $sent = $mail->send($adminEmail, 'Gmind Admin', $subject, $htmlBody, $textBody);

                    if ($sent) {
                        $log('SUCCESS: Notification sent to ' . $adminEmail . ' via App\Core\Mail');
                        return; // Success!
                    } else {
                        $log('Strategy 1 FAILED: App\Core\Mail — ' . $mail->getLastError());
                    }
                } else {
                    $log('Strategy 1 SKIP: Mail not available or not configured. Available=' . ($mail->isAvailable() ? 'yes' : 'no') . ', Configured=' . ($mail->isConfigured() ? 'yes' : 'no'));
                }
            } catch (\Throwable $mailEx) {
                $log('Strategy 1 EXCEPTION: App\Core\Mail — ' . $mailEx->getMessage());
            }

            // === Strategy 2: Direct PHPMailer usage (bypass wrapper) ===
            try {
                $phpMailerPath = $this->findPHPMailerDirect();
                $log('Strategy 2: PHPMailer path found = ' . ($phpMailerPath ?? 'NULL'));

                if ($phpMailerPath) {
                    require_once $phpMailerPath . '/PHPMailer.php';
                    require_once $phpMailerPath . '/SMTP.php';
                    require_once $phpMailerPath . '/Exception.php';

                    // Read SMTP settings directly from DB
                    $smtpSettings = $this->readSmtpSettingsDirect();
                    $log('Strategy 2: SMTP settings = host=' . ($smtpSettings['smtp_host'] ?? 'EMPTY') . ', from=' . ($smtpSettings['smtp_from_email'] ?? 'EMPTY') . ', port=' . ($smtpSettings['smtp_port'] ?? 'EMPTY'));

                    if (!empty($smtpSettings['smtp_host']) && !empty($smtpSettings['smtp_from_email'])) {
                        $phpMail = new \PHPMailer\PHPMailer\PHPMailer(true);

                        $phpMail->isSMTP();
                        $phpMail->Host       = $smtpSettings['smtp_host'];
                        $phpMail->Port       = (int) ($smtpSettings['smtp_port'] ?? 465);
                        $phpMail->SMTPAuth   = !empty($smtpSettings['smtp_username']);
                        $phpMail->Username   = $smtpSettings['smtp_username'] ?? '';
                        $phpMail->Password   = $smtpSettings['smtp_password'] ?? '';

                        if (($smtpSettings['smtp_encryption'] ?? 'ssl') === 'ssl') {
                            $phpMail->SMTPSecure = \PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_SMTPS;
                        } elseif (($smtpSettings['smtp_encryption'] ?? '') === 'tls') {
                            $phpMail->SMTPSecure = \PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS;
                        }

                        $phpMail->SMTPOptions = [
                            'ssl' => [
                                'verify_peer'      => false,
                                'verify_peer_name' => false,
                                'allow_self_signed' => true,
                            ],
                        ];

                        $phpMail->CharSet = 'UTF-8';
                        $phpMail->Timeout = 30;

                        $phpMail->setFrom($smtpSettings['smtp_from_email'], $smtpSettings['smtp_from_name'] ?? 'Gmind Institute');
                        $phpMail->addAddress($adminEmail, 'Gmind Admin');

                        $phpMail->isHTML(true);
                        $phpMail->Subject = $subject;
                        $phpMail->Body    = $htmlBody;
                        $phpMail->AltBody = $textBody;

                        // Enable debug output for troubleshooting
                        $phpMail->SMTPDebug = 2;
                        $phpMail->Debugoutput = function($str, $level) use ($log) {
                            $log('SMTP Debug [level ' . $level . ']: ' . trim($str));
                        };

                        $phpMail->send();
                        $log('SUCCESS: Notification sent to ' . $adminEmail . ' via direct PHPMailer');
                        return; // Success!
                    } else {
                        $log('Strategy 2 SKIP: SMTP not configured in DB');
                    }
                } else {
                    $log('Strategy 2 SKIP: PHPMailer library not found anywhere');
                }
            } catch (\Throwable $directEx) {
                $log('Strategy 2 EXCEPTION: Direct PHPMailer — ' . $directEx->getMessage());
            }

            // === Strategy 3: PHP mail() fallback ===
            try {
                $log('Strategy 3: Trying PHP mail() fallback');
                $headers  = "From: Gmind Institute <noreply@gmind.in>\r\n";
                $headers .= "Reply-To: " . htmlspecialchars($email, ENT_QUOTES, 'UTF-8') . "\r\n";
                $headers .= "MIME-Version: 1.0\r\n";
                $headers .= "Content-Type: text/html; charset=UTF-8\r\n";

                $mailResult = mail($adminEmail, $subject, $htmlBody, $headers);
                if ($mailResult) {
                    $log('SUCCESS: Notification sent to ' . $adminEmail . ' via PHP mail() fallback');
                } else {
                    $log('Strategy 3 FAILED: PHP mail() returned false');
                }
            } catch (\Throwable $mailFallbackEx) {
                $log('Strategy 3 EXCEPTION: PHP mail() — ' . $mailFallbackEx->getMessage());
            }

        } catch (\Throwable $e) {
            // Email notification is best-effort — never block the form submission
            if (isset($log)) {
                $log('OUTER EXCEPTION: ' . $e->getMessage());
            }
            error_log('Demo class email outer exception: ' . $e->getMessage());
        }
    }

    /**
     * Find PHPMailer library path directly (bypass Mail wrapper).
     */
    private function findPHPMailerDirect(): ?string
    {
        $docRoot = rtrim($_SERVER['DOCUMENT_ROOT'] ?? '', '/');
        $basePath = defined('BASE_PATH') ? BASE_PATH : '';
        $relRoot = dirname(__DIR__, 2); // 2 levels up from app/Controllers = project root

        $paths = [
            $docRoot . $basePath . '/phpmailer/src',
            $docRoot . '/phpmailer/src',
            $relRoot . '/phpmailer/src',
            $docRoot . $basePath . '/PHPMailer/src',
            $docRoot . '/PHPMailer/src',
            $relRoot . '/PHPMailer/src',
            $docRoot . $basePath . '/vendor/phpmailer/phpmailer/src',
            $docRoot . '/vendor/phpmailer/phpmailer/src',
            $relRoot . '/vendor/phpmailer/phpmailer/src',
        ];

        foreach ($paths as $path) {
            $realPath = realpath($path);
            if ($realPath && is_dir($realPath) && file_exists($realPath . '/PHPMailer.php')) {
                return $realPath;
            }
        }

        return null;
    }

    /**
     * Read SMTP settings directly from the database (bypass Mail wrapper).
     */
    private function readSmtpSettingsDirect(): array
    {
        $result = [];
        $keys = ['smtp_host', 'smtp_port', 'smtp_username', 'smtp_password', 'smtp_encryption', 'smtp_from_email', 'smtp_from_name'];

        try {
            // Method 1: setting_key / setting_value
            $placeholders = implode(',', array_fill(0, count($keys), '?'));
            $stmt = $this->db->prepare(
                "SELECT `setting_key`, `setting_value` FROM `settings` WHERE `setting_key` IN ({$placeholders})"
            );
            $stmt->execute($keys);
            $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);
            foreach ($rows as $row) {
                $k = $row['setting_key'] ?? '';
                if (in_array($k, $keys, true)) {
                    $result[$k] = $row['setting_value'] ?? '';
                }
            }

            // Method 2: key_name / value — fill gaps
            $stmt = $this->db->prepare(
                "SELECT `key_name`, `value` FROM `settings` WHERE `key_name` IN ({$placeholders})"
            );
            $stmt->execute($keys);
            $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);
            foreach ($rows as $row) {
                $k = $row['key_name'] ?? '';
                $v = $row['value'] ?? '';
                if (in_array($k, $keys, true)) {
                    if (!isset($result[$k]) || $result[$k] === '') {
                        $result[$k] = $v;
                    }
                }
            }
        } catch (\Throwable $e) {
            error_log('Demo class email: readSmtpSettingsDirect failed — ' . $e->getMessage());
        }

        return $result;
    }
}
