<?php
/**
 * Pattern Course Assignment Controller
 * 
 * Lists all courses and lets super admin assign cert/marksheet patterns
 */

namespace SuperAdmin\Controllers;

use SuperAdmin\Controllers\SuperAdminBaseController;
use App\Helpers\DocumentGenerator;

class PatternCourseController extends SuperAdminBaseController
{
    private function bp(): string
    {
        return defined('BASE_PATH') ? BASE_PATH : '/gmind';
    }

    /**
     * List all courses with their assigned patterns
     */
    public function index(): void
    {
        requireSuperAdmin();

        // Get all courses with their pattern info
        $sql = "SELECT c.*,
                    COALESCE(cp.name, '(none)') AS cert_pattern_name,
                    COALESCE(mp.name, '(none)') AS marksheet_pattern_name,
                    c.cert_pattern_id,
                    c.marksheet_pattern_id
                FROM `courses` c
                LEFT JOIN `certificate_patterns` cp ON c.`cert_pattern_id` = cp.`id`
                LEFT JOIN `certificate_patterns` mp ON c.`marksheet_pattern_id` = mp.`id`
                ORDER BY c.`name` ASC";
        $stmt = $this->db->query($sql);
        $courses = $stmt->fetchAll() ?: [];

        // ✅ FIX: Get locked patterns using $this->db (NOT static method)
        $stmt = $this->db->query("SELECT `id`, `name`, `is_default` FROM `certificate_patterns` WHERE `status` = 'locked' ORDER BY `is_default` DESC, `name` ASC");
        $lockedPatterns = $stmt->fetchAll() ?: [];

        $this->superAdminView('patterns/course_assignment', [
            'title'           => 'Assign Patterns to Courses',
            'currentPage'     => 'patterns',
            'courses'         => $courses,
            'lockedPatterns'  => $lockedPatterns,
            'csrfToken'       => $this->csrfToken ?? '',
        ]);
    }

    /**
     * Save pattern assignment (AJAX)
     */
    public function save(): void
    {
        requireSuperAdmin();
        header('Content-Type: application/json');

        if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
            echo json_encode(['error' => 'Invalid request']);
            return;
        }

        $courseId  = (int)($_POST['course_id'] ?? 0);
        $certPatternId = (int)($_POST['cert_pattern_id'] ?? 0);
        $marksheetPatternId = (int)($_POST['marksheet_pattern_id'] ?? 0);

        if (!$courseId) {
            echo json_encode(['error' => 'Course ID required']);
            return;
        }

        try {
            // Update cert pattern (set to NULL if 0)
            if ($certPatternId > 0) {
                $stmt = $this->db->prepare("UPDATE `courses` SET `cert_pattern_id` = ? WHERE `id` = ?");
                $stmt->execute([$certPatternId, $courseId]);
            } else {
                $stmt = $this->db->prepare("UPDATE `courses` SET `cert_pattern_id` = NULL WHERE `id` = ?");
                $stmt->execute([$courseId]);
            }

            // Update marksheet pattern
            if ($marksheetPatternId > 0) {
                $stmt = $this->db->prepare("UPDATE `courses` SET `marksheet_pattern_id` = ? WHERE `id` = ?");
                $stmt->execute([$marksheetPatternId, $courseId]);
            } else {
                $stmt = $this->db->prepare("UPDATE `courses` SET `marksheet_pattern_id` = NULL WHERE `id` = ?");
                $stmt->execute([$courseId]);
            }

            echo json_encode(['success' => true, 'message' => 'Pattern assigned successfully!']);
        } catch (\Throwable $e) {
            echo json_encode(['error' => $e->getMessage()]);
        }
    }

    /**
     * Test generate certificate/marksheet for a course with sample data
     */
    public function testGenerate(): void
    {
        requireSuperAdmin();

        $courseId = (int)($_GET['course_id'] ?? 0);
        $docType  = $_GET['doc_type'] ?? 'certificate';

        if (!$courseId) {
            die('Course ID required');
        }

        // Get course + pattern info
        $stmt = $this->db->prepare("
            SELECT c.*, cp.name AS cert_pattern_name, mp.name AS marksheet_pattern_name,
                   cp.cert_background_path, mp.marksheet_background_path,
                   cp.page_width, cp.page_height
            FROM `courses` c
            LEFT JOIN `certificate_patterns` cp ON c.`cert_pattern_id` = cp.`id`
            LEFT JOIN `certificate_patterns` mp ON c.`marksheet_pattern_id` = mp.`id`
            WHERE c.`id` = ?
        ");
        $stmt->execute([$courseId]);
        $course = $stmt->fetch();

        if (!$course) {
            die('Course not found');
        }

        // Determine which pattern to use
        if ($docType === 'certificate') {
            $patternId = $course['cert_pattern_id'] ?? null;
            $bgPath = $course['cert_background_path'] ?? '';
            $patternName = $course['cert_pattern_name'] ?? '';
        } else {
            $patternId = $course['marksheet_pattern_id'] ?? null;
            $bgPath = $course['marksheet_background_path'] ?? '';
            $patternName = $course['marksheet_pattern_name'] ?? '';
        }

        if (!$patternId) {
            die("No {$docType} pattern assigned to this course. Please assign a pattern first.");
        }

        if (empty($bgPath)) {
            die("Background image missing for pattern: {$patternName}");
        }

        $fullBgPath = $_SERVER['DOCUMENT_ROOT'] . $bgPath;
        if (!file_exists($fullBgPath)) {
            die("Background file not found: {$fullBgPath}");
        }

        // Load pattern + fields
        $stmt = $this->db->prepare("SELECT * FROM `certificate_patterns` WHERE `id` = ?");
        $stmt->execute([$patternId]);
        $pattern = $stmt->fetch();

        $stmt = $this->db->prepare("
            SELECT * FROM `certificate_pattern_fields`
            WHERE `pattern_id` = ? AND `doc_type` = ? AND `is_enabled` = 1
            ORDER BY `id` ASC
        ");
        $stmt->execute([$patternId, $docType]);
        $fields = $stmt->fetchAll() ?: [];

        // Build sample student data
        $sampleData = [
            'student_name'   => 'RAHUL KUMAR SHARMA',
            'father_name'    => 'SURESH KUMAR SHARMA',
            'enrollment_no'  => 'GM2025' . str_pad($courseId, 4, '0', STR_PAD_LEFT),
            'certificate_no' => 'CERT-' . date('Y') . '-' . str_pad($courseId, 4, '0', STR_PAD_LEFT),
            'course'         => $course['name'] ?? 'Test Course',
            'branch_name'    => 'MAIN BRANCH, LUCKNOW',
            'branch_code'    => 'GMBR01',
            'duration'       => $course['duration'] ?? '6 MONTHS',
            'date_of_issue'  => date('d/m/Y'),
            'from_date'      => $this->calculateFromDate($course['duration'] ?? ''),
            'to_date'        => $this->calculateToDate($course['duration'] ?? ''),
            'percentage'     => '85.5%',
            'grade'          => 'A+',
            'photo'          => '',
            'qr_data'        => 'CERT:' . $courseId . '|TEST',
            'subjects' => $this->getCourseSubjects($courseId),
        ];

        try {
            $generator = new DocumentGenerator();
            $pdf = $generator->generateFromPattern([
                'pattern'    => $pattern,
                'fields'     => $fields,
                'student'    => $sampleData,
                'doc_type'   => $docType,
                'bg_path'    => $fullBgPath,
                'is_preview' => true,
            ]);

            $filename = 'test_' . $docType . '_course' . $courseId . '.pdf';
            $pdf->Output('I', $filename);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo 'PDF generation failed: ' . htmlspecialchars($e->getMessage());
        }
    }

    /**
     * Get subjects for a course (for marksheet test)
     */
    private function getCourseSubjects(int $courseId): array
    {
        $stmt = $this->db->prepare("SELECT `subjects` FROM `courses` WHERE `id` = ?");
        $stmt->execute([$courseId]);
        $row = $stmt->fetch();

        if (!empty($row['subjects'])) {
            $subjects = json_decode($row['subjects'], true);
            if (is_array($subjects)) {
                $result = [];
                foreach ($subjects as $s) {
                    $result[] = [
                        'name'     => $s['name'] ?? $s['subject_name'] ?? 'Subject',
                        'max'      => (int)($s['max_marks'] ?? $s['max'] ?? 100),
                        'obtained' => rand(60, 95),
                    ];
                }
                if (!empty($result)) return $result;
            }
        }

        // Default sample subjects
        return [
            ['name' => 'Fundamentals of Computer', 'max' => 100, 'obtained' => 88],
            ['name' => 'MS Office',                'max' => 100, 'obtained' => 92],
            ['name' => 'Internet & HTML',          'max' => 100, 'obtained' => 78],
            ['name' => 'Tally ERP',                'max' => 100, 'obtained' => 85],
            ['name' => 'Photoshop',                'max' => 100, 'obtained' => 80],
            ['name' => 'Programming in C',         'max' => 100, 'obtained' => 90],
            ['name' => 'Practical Lab',            'max' => 100, 'obtained' => 95],
        ];
    }

    /**
     * Calculate sample "from date" label (today's date minus duration)
     */
    private function calculateFromDate(string $duration): string
    {
        $dt = new \DateTime();
        // Subtract full duration (no -1 here, because we want full duration back)
        $this->addDurationToDate($dt, '-' . $duration, false);
        return strtoupper($dt->format('M Y'));
    }

    /**
     * Calculate sample "to date" label (today's date)
     */
    private function calculateToDate(string $duration): string
    {
        $dt = new \DateTime();
        return strtoupper($dt->format('M Y'));
    }

    /**
     * Add course duration to a DateTime object.
     * Supports formats like "3 Months", "6 Months", "1 Year", "2 Years", "1.5 Years"
     * If duration starts with "-", it subtracts instead.
     *
     * IMPORTANT: Duration is INCLUSIVE when $inclusive=true (default):
     *   "3 Months" → JAN + 2 months = MAR (3 months total)
     *   "1 Year"   → JAN + 11 months = DEC (12 months total, same year)
     */
    private function addDurationToDate(\DateTime $date, string $duration, bool $inclusive = true): void
    {
        $duration = trim($duration);
        $sign = '+';
        if (strpos($duration, '-') === 0) {
            $sign = '-';
            $duration = ltrim($duration, '-');
        }

        $subtract = $inclusive ? 1 : 0;
        $monthsToAdd = 0;
        $daysToAdd = 0;

        // Try to parse "X Months"
        if (preg_match('/^([\d.]+)\s*month/i', $duration, $m)) {
            $months = (int)round((float)$m[1]);
            $monthsToAdd = max(0, $months - $subtract);
        }
        // Try to parse "X Years"
        elseif (preg_match('/^([\d.]+)\s*year/i', $duration, $m)) {
            $years = (float)$m[1];
            $totalMonths = (int)round($years * 12);
            $monthsToAdd = max(0, $totalMonths - $subtract);
        }
        // Try to parse "X Days"
        elseif (preg_match('/^([\d.]+)\s*day/i', $duration, $m)) {
            $days = (int)round((float)$m[1]);
            $daysToAdd = max(0, $days - $subtract);
        }
        // Try to parse "X Weeks"
        elseif (preg_match('/^([\d.]+)\s*week/i', $duration, $m)) {
            $weeks = (int)round((float)$m[1]);
            $days = $weeks * 7;
            $daysToAdd = max(0, $days - $subtract);
        }
        else {
            // Unknown — default 6 months
            $monthsToAdd = max(0, 6 - $subtract);
        }

        if ($monthsToAdd > 0) {
            $date->modify("{$sign}{$monthsToAdd} months");
        }
        if ($daysToAdd > 0) {
            $date->modify("{$sign}{$daysToAdd} days");
        }
    }
}
