<?php
/**
 * Public Certificate Verification Controller (Standalone — no base class)
 *
 * Accessible at: /verify/{documentNumber}
 * Shows full student + certificate info when QR code is scanned.
 */

namespace App\Controllers;

class VerificationController
{
    /**
     * Verify page — show student info by document number
     */
    public function verify(?string $documentNumber = null): void
    {
        $documentNumber = trim($documentNumber ?? '');
        $hash = trim($_GET['h'] ?? '');

        if (empty($documentNumber)) {
            $this->renderSearch();
            return;
        }

        try {
            $db = $this->getDb();

            // Load certificate by certificate_no
            $stmt = $db->prepare(
                "SELECT c.*,
                        s.enrollment_no, s.father_name, s.dob, s.admission_date,
                        s.address, s.city, s.state, s.pin_code,
                        COALESCE(c.student_name, u.name, 'Unknown') AS student_name,
                        u.photo,
                        COALESCE(c.course_name, cs.name, '—') AS course_name,
                        cs.duration,
                        b.name AS branch_name, b.branch_code, b.city AS branch_city, b.state AS branch_state,
                        t.name AS template_name, t.type AS doc_type
                 FROM certificates c
                 LEFT JOIN students s ON c.student_id = s.id
                 LEFT JOIN users u ON s.user_id = u.id
                 LEFT JOIN courses cs ON c.course_id = cs.id
                 LEFT JOIN branches b ON c.branch_id = b.id
                 LEFT JOIN certificate_templates t ON c.template_id = t.id
                 WHERE c.certificate_no = :no
                    OR c.verification_url LIKE :like
                 LIMIT 1"
            );
            $stmt->execute([
                ':no'   => $documentNumber,
                ':like' => '%' . $documentNumber . '%',
            ]);
            $doc = $stmt->fetch();

            if (!$doc) {
                $this->renderNotFound($documentNumber);
                return;
            }

            // Verify hash (optional security check)
            $hashValid = true;
            if (!empty($hash) && !empty($doc['qr_hash'])) {
                $hashValid = (strpos($doc['qr_hash'], $hash) === 0);
            }

            // Parse subjects
            $subjectsData = [];
            if (!empty($doc['subjects_json'])) {
                $subjectsData = json_decode($doc['subjects_json'], true) ?: [];
            }

            // Build subjects array
            $subjects = [];
            if (!empty($subjectsData['subjects'])) {
                $subjList = $subjectsData['subjects'];
                $maxList  = $subjectsData['max_marks'] ?? [];
                $obtList  = $subjectsData['obtained_marks'] ?? [];
                for ($i = 0; $i < count($subjList); $i++) {
                    $max = (int)($maxList[$i] ?? 100);
                    $obt = (int)($obtList[$i] ?? 0);
                    $pct = $max > 0 ? round(($obt / $max) * 100, 1) : 0;
                    $subjects[] = [
                        'name'      => $subjList[$i],
                        'max'       => $max,
                        'obtained'  => $obt,
                        'percent'   => $pct,
                        'grade'     => $this->calcGrade($pct),
                    ];
                }
            }

            // Format dates
            $fromLabel = $subjectsData['from_label'] ?? '';
            $toLabel   = $subjectsData['to_label'] ?? '';
            if (empty($fromLabel) && !empty($doc['session_from'])) {
                $dt = \DateTime::createFromFormat('Y-m-d', $doc['session_from']);
                if ($dt) $fromLabel = $dt->format('M Y');
            }
            if (empty($toLabel) && !empty($doc['session_to'])) {
                $dt = \DateTime::createFromFormat('Y-m-d', $doc['session_to']);
                if ($dt) $toLabel = $dt->format('M Y');
            }

            $issueDate = '';
            if (!empty($doc['issue_date'])) {
                $dt = \DateTime::createFromFormat('Y-m-d', $doc['issue_date']);
                if ($dt) $issueDate = $dt->format('d M Y');
            }

            $this->renderResult($doc, $subjects, $fromLabel, $toLabel, $issueDate, $hashValid, $documentNumber);

        } catch (\Throwable $e) {
            error_log('Verify error: ' . $e->getMessage());
            $this->renderError($e->getMessage());
        }
    }

    /**
     * Search page — user enters document number manually
     */
    public function search(): void
    {
        $documentNumber = trim($_POST['document_number'] ?? '');
        if (!empty($documentNumber)) {
            header('Location: ' . (defined('BASE_PATH') ? BASE_PATH : '/gmind') . '/verify/' . urlencode($documentNumber));
            exit;
        }
        $this->renderSearch();
    }

    public function index(): void
    {
        $this->search();
    }

    // ─── View Renderers (standalone, no base class) ────────────────────────

    private function renderSearch(): void
    {
        $bp = defined('BASE_PATH') ? BASE_PATH : '/gmind';
        $title = 'Verify Certificate';
        include $this->viewPath('verify/search');
    }

    private function renderNotFound(string $docNumber): void
    {
        $bp = defined('BASE_PATH') ? BASE_PATH : '/gmind';
        $title = 'Not Found';
        $docNumber = htmlspecialchars($docNumber);
        include $this->viewPath('verify/not_found');
    }

    private function renderError(string $error): void
    {
        $bp = defined('BASE_PATH') ? BASE_PATH : '/gmind';
        $title = 'Error';
        $error = htmlspecialchars($error);
        include $this->viewPath('verify/error');
    }

    private function renderResult(array $doc, array $subjects, string $fromLabel, string $toLabel, string $issueDate, bool $hashValid, string $docNumber): void
    {
        $bp = defined('BASE_PATH') ? BASE_PATH : '/gmind';
        $title = 'Verify: ' . $docNumber;
        // Make variables available to view
        extract(compact('doc', 'subjects', 'fromLabel', 'toLabel', 'issueDate', 'hashValid', 'docNumber', 'bp'));
        include $this->viewPath('verify/result');
    }

    private function viewPath(string $relativePath): string
    {
        $base = dirname(dirname(__DIR__)) . '/app/Views/';
        return $base . $relativePath . '.php';
    }

    // ─── Helpers ────────────────────────────────────────────────────────────

    private function calcGrade(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 getDb(): \PDO
    {
        if (defined('DB_HOST')) {
            $dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8mb4";
            return new \PDO($dsn, DB_USER, DB_PASS, [
                \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
                \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
            ]);
        }
        // Fallback: load config file
        $configFile = dirname(dirname(dirname(__DIR__))) . '/config/database.php';
        if (file_exists($configFile)) {
            require_once $configFile;
            $dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8mb4";
            return new \PDO($dsn, DB_USER, DB_PASS, [
                \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
                \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
            ]);
        }
        throw new \Exception('Database config not loaded');
    }
}
