<?php

declare(strict_types=1);

namespace BranchAdmin\Controllers;

use App\Helpers\DocumentGenerator;

/**
 * Branch Certificate & Marksheet Controller
 *
 * Phase 5 flow:
 *   1. Branch admin opens a student → clicks "Create Result"
 *   2. Selects completion month (last 2 years dropdown)
 *   3. Subject marks auto-load from the student's course
 *   4. Branch enters marks manually OR uses Random Marks / Target Grade
 *   5. Chooses payment: Online ₹200 (wallet) OR Offline (transaction ID)
 *   6. Submits → creates TWO certificate rows (cert + marksheet) with
 *      status='pending_approval'
 *   7. Super Admin sees the request → verifies → clicks "Approve & Generate"
 *      → ₹200 deducted from wallet (if online) → PDFs generated for both →
 *      Branch can download
 *
 * URL prefix: /branch/students/{id}/create-result
 */
class BranchCertMarksheetController extends BranchBaseController
{
    /**
     * Show the "Create Result" form for a student.
     */
    public function createResult(int $studentId): void
    {
        requireBranchAdmin();
        $branchId = $this->getBranchId();

        // Fetch student (must belong to this branch)
        $stmt = $this->db->prepare(
            "SELECT s.*, u.name, u.email, u.phone, u.photo, c.name AS course_name, c.duration, c.subjects
             FROM students s
             LEFT JOIN users u ON s.user_id = u.id
             LEFT JOIN courses c ON s.course_id = c.id
             WHERE s.id = :sid AND s.branch_id = :bid LIMIT 1"
        );
        $stmt->execute([':sid' => $studentId, ':bid' => $branchId]);
        $student = $stmt->fetch() ?: null;
        if (!$student) {
            flash('error', 'Student not found.');
            redirect(BASE_PATH . '/branch/students');
        }

        // Parse course subjects
        $subjects = [];
        if (!empty($student['subjects'])) {
            $decoded = json_decode($student['subjects'], true);
            if (is_array($decoded)) $subjects = $decoded;
        }
        // Fallback: if no subjects, create a default set
        if (empty($subjects)) {
            $subjects = [
                ['name' => 'Theory', 'max_marks' => 100],
                ['name' => 'Practical', 'max_marks' => 100],
            ];
        }

        $this->branchAdminView('students/create_result', [
            'title'       => 'Create Result: ' . ($student['name'] ?? ''),
            'currentPage' => 'students',
            'student'     => $student,
            'course'      => ['name' => $student['course_name'] ?? '', 'duration' => $student['duration'] ?? ''],
            'subjects'    => $subjects,
        ]);
    }

    /**
     * Save the result + create certificate + marksheet requests
     * (status='pending_approval'). Super Admin will approve later.
     */
    public function storeResult(int $studentId): void
    {
        requireBranchAdmin();
        $this->validateCsrf();
        $branchId = $this->getBranchId();
        $this->ensurePaymentColumns();

        // Fetch student
        $stmt = $this->db->prepare(
            "SELECT s.*, u.name, u.photo, c.name AS course_name, c.duration
             FROM students s
             LEFT JOIN users u ON s.user_id = u.id
             LEFT JOIN courses c ON s.course_id = c.id
             WHERE s.id = :sid AND s.branch_id = :bid LIMIT 1"
        );
        $stmt->execute([':sid' => $studentId, ':bid' => $branchId]);
        $student = $stmt->fetch() ?: null;
        if (!$student) {
            flash('error', 'Student not found.');
            redirect(BASE_PATH . '/branch/students');
        }

        // Read POST
        $completionMonth = trim($_POST['completion_month'] ?? '');        // e.g. "2026-06"
        $fromMonth       = trim($_POST['from_month'] ?? '');              // e.g. "2025-06"
        $subjectNames    = $_POST['subject_name'] ?? [];
        $maxMarks        = $_POST['max_marks'] ?? [];
        $obtMarks        = $_POST['obtained_marks'] ?? [];
        $paymentMode     = trim($_POST['payment_mode'] ?? 'offline');
        $transactionId   = trim($_POST['transaction_id'] ?? '');
        $paymentDate     = trim($_POST['payment_date'] ?? date('Y-m-d'));
        $totalAmount     = (float)($_POST['total_amount'] ?? 200);

        // Validate
        if (empty($completionMonth)) {
            flash('error', 'Please select the completion month.');
            redirect(BASE_PATH . '/branch/students/' . $studentId . '/create-result');
        }
        $isOnline = in_array($paymentMode, ['online', 'upi', 'wallet'], true);
        if (!$isOnline && $transactionId === '') {
            flash('error', 'Please enter the Transaction ID for offline payment.');
            redirect(BASE_PATH . '/branch/students/' . $studentId . '/create-result');
        }

        // Calculate totals + grade + division
        $totalMax = 0; $totalObt = 0;
        $subjectsData = [];
        for ($i = 0; $i < count($subjectNames); $i++) {
            $m = (float)($maxMarks[$i] ?? 100);
            $o = (float)($obtMarks[$i] ?? 0);
            if ($o > $m) $o = $m;
            $totalMax += $m;
            $totalObt += $o;
            $subjectsData[] = ['name' => $subjectNames[$i], 'max' => $m, 'obtained' => $o];
        }
        $percentage = $totalMax > 0 ? round(($totalObt / $totalMax) * 100, 2) : 0;
        $grade = $this->calculateGrade($percentage);
        $division = $this->calculateDivision($percentage);

        // Format from/to dates as "JAN 2025" / "DEC 2025"
        $fromDateLabel = '';
        $toDateLabel = '';
        if (!empty($fromMonth)) {
            $dt = \DateTime::createFromFormat('Y-m', $fromMonth);
            if ($dt) $fromDateLabel = strtoupper($dt->format('M Y'));
        }
        if (!empty($completionMonth)) {
            $dt = \DateTime::createFromFormat('Y-m', $completionMonth);
            if ($dt) $toDateLabel = strtoupper($dt->format('M Y'));
        }

        // Fetch branch info
        $stmt = $this->db->prepare("SELECT * FROM branches WHERE id = :bid LIMIT 1");
        $stmt->execute([':bid' => $branchId]);
        $branch = $stmt->fetch() ?: [];

        // Find certificate + marksheet templates for this course
        $stmt = $this->db->prepare(
            "SELECT * FROM certificate_templates
             WHERE course_id = :cid AND is_active = 1 AND type IN ('certificate','marksheet')"
        );
        $stmt->execute([':cid' => $student['course_id']]);
        $templates = $stmt->fetchAll() ?: [];

        if (empty($templates)) {
            flash('error', 'No certificate/marksheet templates mapped for this course. Please ask the Super Admin to map them first (Super Admin → Cert & Marksheet Mapping).');
            redirect(BASE_PATH . '/branch/students/' . $studentId . '/create-result');
        }

        try {
            $this->db->beginTransaction();
            $generatedDocNumbers = [];
            $generatedCertIds = [];

            foreach ($templates as $template) {
                $docType = $template['type'];

                // Generate document number
                $serialPrefix = ($docType === 'marksheet') ? 'MS' : 'GMIND';
                $stmt = $this->db->prepare("SELECT COUNT(*) AS c FROM certificates WHERE certificate_no LIKE :pfx");
                $stmt->execute([':pfx' => $serialPrefix . '-%']);
                $lastNum = (int)($stmt->fetch()['c'] ?? 0) + 1;
                $documentNumber = $serialPrefix . '-' . date('Y') . '-' . str_pad((string)$lastNum, 5, '0', STR_PAD_LEFT);

                // Verification hash + URL
                $verificationHash = DocumentGenerator::generateVerificationHash($studentId, $documentNumber);
                $verificationUrl  = DocumentGenerator::buildVerificationUrl($documentNumber, $verificationHash);

                // Insert into certificates table
                $insertSql = "INSERT INTO `certificates`
                    (`certificate_no`, `student_id`, `branch_id`, `course_id`,
                     `student_name`, `course_name`, `grade`, `percentage`, `division`,
                     `session_from`, `session_to`, `issue_date`,
                     `status`, `template_id`, `created_by`,
                     `qr_hash`, `verification_url`,
                     `payment_mode`, `transaction_id`, `payment_date`, `amount_paid`,
                     `subjects_json`,
                     `created_at`, `updated_at`)
                 VALUES
                    (:cert_no, :sid, :bid, :course_id,
                     :sname, :cname, :grade, :pct, :div,
                     :sf, :st, :idate,
                     'pending_approval', :tid, :created_by,
                     :qr_hash, :verify_url,
                     :pmode, :txn, :pdate, :amt,
                     :sjson,
                     NOW(), NOW())";

                $this->db->prepare($insertSql)->execute([
                    ':cert_no'   => $documentNumber,
                    ':sid'       => $studentId,
                    ':bid'       => $branchId,
                    ':course_id' => $student['course_id'] ?? null,
                    ':sname'     => $student['name'] ?? '',
                    ':cname'     => $student['course_name'] ?? '',
                    ':grade'     => $grade,
                    ':pct'       => $percentage,
                    ':div'       => $division,
                    ':sf'        => $fromMonth . '-01',
                    ':st'        => $completionMonth . '-01',
                    ':idate'     => date('Y-m-d'),
                    ':tid'       => $template['id'],
                    ':created_by' => $_SESSION['user_id'] ?? null,
                    ':qr_hash'   => $verificationHash,
                    ':verify_url'=> $verificationUrl,
                    ':pmode'     => $paymentMode,
                    ':txn'       => $transactionId ?: null,
                    ':pdate'     => $paymentDate ?: null,
                    ':amt'       => $totalAmount,
                    ':sjson'     => json_encode([
                        'subjects'      => $subjectNames,
                        'max_marks'     => $maxMarks,
                        'obtained_marks'=> $obtMarks,
                        'from_label'    => $fromDateLabel,
                        'to_label'      => $toDateLabel,
                    ]),
                ]);
                $certId = (int)$this->db->lastInsertId();
                $generatedCertIds[] = $certId;
                $generatedDocNumbers[] = $documentNumber . ' (' . ucfirst($docType) . ')';

                // Timeline
                $this->db->prepare(
                    "INSERT INTO `certificate_timeline` (`certificate_id`, `event`, `description`, `created_at`)
                     VALUES (:cid, 'requested', :desc, NOW())"
                )->execute([
                    ':cid'  => $certId,
                    ':desc' => "Result submitted by branch. Completion: {$toDateLabel}, {$grade} ({$percentage}%). Payment: {$paymentMode}" . ($transactionId ? ", Txn: {$transactionId}" : "") . ". Awaiting Super Admin approval.",
                ]);
            }

            $this->db->commit();

            $docList = implode(', ', $generatedDocNumbers);
            $this->auditLog('result_submitted_for_approval', 'certificates', $generatedCertIds[0] ?? 0,
                "Submitted result for student {$student['name']} ({$grade}, {$percentage}%). Docs: {$docList}. Payment: {$paymentMode}.");

            flash('success', "✅ Result submitted for approval! Documents: {$docList}. Completion: {$toDateLabel}. Grade: {$grade} ({$percentage}%). Total: ₹{$totalAmount} ({$paymentMode}). Super Admin will verify and approve — once approved, both PDFs will be generated and downloadable from the Documents page.");
        } catch (\Throwable $e) {
            try { $this->db->rollBack(); } catch (\Throwable $e2) {}
            error_log('BranchCertMarksheet storeResult error: ' . $e->getMessage());
            flash('error', 'Error submitting result: ' . $e->getMessage());
        }
        redirect(BASE_PATH . '/branch/documents');
    }

    // ========================================================================
    // PRIVATE HELPERS
    // ========================================================================

    private function calculateGrade(float $pct): string
    {
        if ($pct >= 90) return 'A+';
        if ($pct >= 80) return 'A';
        if ($pct >= 70) return 'B+';
        if ($pct >= 60) return 'B';
        if ($pct >= 45) return 'C';
        if ($pct >= 33) return 'D';
        return 'F';
    }

    private function calculateDivision(float $pct): string
    {
        if ($pct >= 60) return 'First Division';
        if ($pct >= 45) return 'Second Division';
        if ($pct >= 33) return 'Third Division';
        return 'Fail';
    }

    private function ensurePaymentColumns(): void
    {
        static $done = false;
        if ($done) return;
        $checks = [
            'payment_mode'    => "ADD COLUMN `payment_mode` VARCHAR(20) NULL DEFAULT NULL",
            'transaction_id'  => "ADD COLUMN `transaction_id` VARCHAR(100) NULL DEFAULT NULL",
            'payment_date'    => "ADD COLUMN `payment_date` DATE NULL DEFAULT NULL",
            'amount_paid'     => "ADD COLUMN `amount_paid` DECIMAL(10,2) NULL DEFAULT NULL",
            'division'        => "ADD COLUMN `division` VARCHAR(20) NULL DEFAULT NULL",
            'session_from'    => "ADD COLUMN `session_from` DATE NULL DEFAULT NULL",
            'session_to'      => "ADD COLUMN `session_to` DATE NULL DEFAULT NULL",
            'pdf_path'        => "ADD COLUMN `pdf_path` VARCHAR(500) NULL DEFAULT NULL",
            'subjects_json'   => "ADD COLUMN `subjects_json` TEXT NULL DEFAULT NULL",
        ];
        foreach ($checks as $col => $ddl) {
            try {
                $stmt = $this->db->prepare(
                    "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
                     WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'certificates' AND COLUMN_NAME = :col"
                );
                $stmt->execute([':col' => $col]);
                if ((int)$stmt->fetchColumn() === 0) {
                    $this->db->exec("ALTER TABLE `certificates` {$ddl}");
                }
            } catch (\Throwable $e) {}
        }
        $done = true;
    }
}
