<?php
declare(strict_types=1);

header('Content-Type: application/json; charset=utf-8');

$configPath = __DIR__ . '/config.php';
$config = file_exists($configPath)
    ? require $configPath
    : [
        'driver' => 'sqlite',
        'sqlite_path' => dirname(dirname(__DIR__)) . '/../academy-data/academy.sqlite',
        'course_slug' => 'creative-digital-production-automation',
        'session_name' => 'kingsoft_academy_session',
    ];

session_name($config['session_name'] ?? 'kingsoft_academy_session');
session_set_cookie_params([
    'lifetime' => 0,
    'path' => '/',
    'secure' => !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off',
    'httponly' => true,
    'samesite' => 'Lax',
]);
if (session_status() !== PHP_SESSION_ACTIVE) {
    session_start();
}

function json_response(array $payload, int $status = 200): void
{
    http_response_code($status);
    echo json_encode($payload);
    exit;
}

function require_method(string $method): void
{
    if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== $method) {
        json_response(['error' => 'Method not allowed.'], 405);
    }
}

function read_json(): array
{
    $raw = file_get_contents('php://input');
    if ($raw === false || trim($raw) === '') {
        return [];
    }

    $data = json_decode($raw, true);
    if (!is_array($data)) {
        json_response(['error' => 'Invalid JSON body.'], 400);
    }

    return $data;
}

function db(): PDO
{
    static $pdo = null;
    global $config;

    if ($pdo instanceof PDO) {
        return $pdo;
    }

    if (($config['driver'] ?? 'sqlite') === 'mysql') {
        $dsn = sprintf(
            'mysql:host=%s;dbname=%s;charset=utf8mb4',
            $config['db_host'],
            $config['db_name']
        );
        $pdo = new PDO($dsn, $config['db_user'], $config['db_pass'], [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    } else {
        $sqlitePath = $config['sqlite_path'];
        $sqliteDir = dirname($sqlitePath);
        if (!is_dir($sqliteDir) && !mkdir($sqliteDir, 0750, true) && !is_dir($sqliteDir)) {
            json_response(['error' => 'Could not create Academy storage directory.'], 500);
        }

        $pdo = new PDO('sqlite:' . $sqlitePath, null, null, [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
        $pdo->exec('PRAGMA foreign_keys = ON');
        migrate_sqlite($pdo);
    }

    return $pdo;
}

function migrate_sqlite(PDO $pdo): void
{
    $pdo->exec(
        'CREATE TABLE IF NOT EXISTS users (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            full_name TEXT NOT NULL,
            email TEXT NOT NULL UNIQUE,
            password_hash TEXT NOT NULL,
            learning_goal TEXT NULL,
            role TEXT NOT NULL DEFAULT "student",
            created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
            updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
        );
        CREATE TABLE IF NOT EXISTS courses (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            slug TEXT NOT NULL UNIQUE,
            title TEXT NOT NULL,
            duration_weeks INTEGER NOT NULL,
            level_label TEXT NOT NULL,
            is_active INTEGER NOT NULL DEFAULT 1,
            created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
        );
        CREATE TABLE IF NOT EXISTS course_classes (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            course_id INTEGER NOT NULL,
            class_slug TEXT NOT NULL,
            week_number INTEGER NOT NULL,
            class_number INTEGER NOT NULL,
            title TEXT NOT NULL,
            duration_label TEXT NOT NULL,
            UNIQUE(course_id, class_slug),
            FOREIGN KEY(course_id) REFERENCES courses(id) ON DELETE CASCADE
        );
        CREATE TABLE IF NOT EXISTS assignments (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            course_id INTEGER NOT NULL,
            assignment_slug TEXT NOT NULL,
            related_class_slug TEXT NOT NULL,
            title TEXT NOT NULL,
            UNIQUE(course_id, assignment_slug),
            FOREIGN KEY(course_id) REFERENCES courses(id) ON DELETE CASCADE
        );
        CREATE TABLE IF NOT EXISTS enrollments (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            user_id INTEGER NOT NULL,
            course_id INTEGER NOT NULL,
            enrolled_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
            UNIQUE(user_id, course_id),
            FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
            FOREIGN KEY(course_id) REFERENCES courses(id) ON DELETE CASCADE
        );
        CREATE TABLE IF NOT EXISTS class_progress (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            user_id INTEGER NOT NULL,
            course_class_id INTEGER NOT NULL,
            completed_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
            UNIQUE(user_id, course_class_id),
            FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
            FOREIGN KEY(course_class_id) REFERENCES course_classes(id) ON DELETE CASCADE
        );
        CREATE TABLE IF NOT EXISTS assignment_submissions (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            user_id INTEGER NOT NULL,
            assignment_id INTEGER NOT NULL,
            submission_text TEXT NULL,
            file_path TEXT NULL,
            status TEXT NOT NULL DEFAULT "submitted",
            marks REAL NULL,
            feedback TEXT NULL,
            submitted_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
            reviewed_at TEXT NULL,
            UNIQUE(user_id, assignment_id),
            FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
            FOREIGN KEY(assignment_id) REFERENCES assignments(id) ON DELETE CASCADE
        );
        CREATE TABLE IF NOT EXISTS project_progress (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            user_id INTEGER NOT NULL,
            course_id INTEGER NOT NULL,
            item_key TEXT NOT NULL,
            is_completed INTEGER NOT NULL DEFAULT 0,
            updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
            UNIQUE(user_id, course_id, item_key),
            FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
            FOREIGN KEY(course_id) REFERENCES courses(id) ON DELETE CASCADE
        );
        CREATE TABLE IF NOT EXISTS certificates (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            user_id INTEGER NOT NULL,
            course_id INTEGER NOT NULL,
            certificate_code TEXT NOT NULL UNIQUE,
            issued_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
            UNIQUE(user_id, course_id),
            FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
            FOREIGN KEY(course_id) REFERENCES courses(id) ON DELETE CASCADE
        );'
    );

    $stmt = $pdo->prepare(
        'INSERT OR IGNORE INTO courses (slug, title, duration_weeks, level_label)
         VALUES (:slug, :title, :duration_weeks, :level_label)'
    );
    $stmt->execute([
        'slug' => 'creative-digital-production-automation',
        'title' => 'Creative Digital Production Automation',
        'duration_weeks' => 3,
        'level_label' => 'Beginner to Intermediate',
    ]);

    $courseId = (int) $pdo
        ->query("SELECT id FROM courses WHERE slug = 'creative-digital-production-automation'")
        ->fetchColumn();

    $classes = [
        ['class-1', 1, 1, 'Introduction to AI in Creative Digital Production', '1 hour 45 minutes'],
        ['class-2', 1, 2, 'Understanding a Client Idea', '1 hour 45 minutes'],
        ['class-3', 1, 3, 'Creating a Creative Brief with AI', '2 hours'],
        ['class-4', 2, 4, 'AI for Website Page Planning', '2 hours'],
        ['class-5', 2, 5, 'AI for App Screen Planning', '1 hour 45 minutes'],
        ['class-6', 2, 6, 'AI for Poster Text, Video Script and Social Media Captions', '2 hours'],
        ['class-7', 3, 7, 'Building a Creative Production Workflow', '1 hour 45 minutes'],
        ['class-8', 3, 8, 'AI-Assisted Quotation Drafting', '1 hour 45 minutes'],
        ['class-9', 3, 9, 'Final Project Presentation', '2 hours'],
    ];
    $classStmt = $pdo->prepare(
        'INSERT OR IGNORE INTO course_classes
         (course_id, class_slug, week_number, class_number, title, duration_label)
         VALUES (:course_id, :class_slug, :week_number, :class_number, :title, :duration_label)'
    );
    foreach ($classes as [$slug, $week, $number, $title, $duration]) {
        $classStmt->execute([
            'course_id' => $courseId,
            'class_slug' => $slug,
            'week_number' => $week,
            'class_number' => $number,
            'title' => $title,
            'duration_label' => $duration,
        ]);
    }

    $assignmentRows = [
        ['assignment-1', 'class-1', 'AI in Digital Production reflection note'],
        ['assignment-2', 'class-2', 'Client Information Sheet'],
        ['assignment-3', 'class-3', 'One-page Creative Brief'],
        ['assignment-4', 'class-4', 'Website Page Plan'],
        ['assignment-5', 'class-5', 'App Screen Outline'],
        ['assignment-6', 'class-6', 'Digital Marketing Content Pack'],
        ['assignment-7', 'class-7', 'Project Workflow and Checklist'],
        ['assignment-8', 'class-8', 'Quotation Draft'],
        ['assignment-9', 'class-9', 'Final Client-ready Presentation'],
    ];
    $assignmentStmt = $pdo->prepare(
        'INSERT OR IGNORE INTO assignments
         (course_id, assignment_slug, related_class_slug, title)
         VALUES (:course_id, :assignment_slug, :related_class_slug, :title)'
    );
    foreach ($assignmentRows as [$slug, $classSlug, $title]) {
        $assignmentStmt->execute([
            'course_id' => $courseId,
            'assignment_slug' => $slug,
            'related_class_slug' => $classSlug,
            'title' => $title,
        ]);
    }
}

function current_user(): ?array
{
    if (empty($_SESSION['user_id'])) {
        return null;
    }

    $stmt = db()->prepare(
        'SELECT id, full_name, email, learning_goal, role, created_at
         FROM users
         WHERE id = :id
         LIMIT 1'
    );
    $stmt->execute(['id' => $_SESSION['user_id']]);
    $user = $stmt->fetch();

    return $user ?: null;
}

function require_user(): array
{
    $user = current_user();
    if (!$user) {
        json_response(['error' => 'Authentication required.'], 401);
    }

    return $user;
}

function require_admin(): array
{
    $user = require_user();
    if (!in_array($user['role'], ['trainer', 'admin'], true)) {
        json_response(['error' => 'Trainer access required.'], 403);
    }

    return $user;
}

function active_course(): array
{
    global $config;
    $stmt = db()->prepare(
        'SELECT id, slug, title, duration_weeks, level_label
         FROM courses
         WHERE slug = :slug AND is_active = 1
         LIMIT 1'
    );
    $stmt->execute(['slug' => $config['course_slug']]);
    $course = $stmt->fetch();

    if (!$course) {
        json_response(['error' => 'Active course not found.'], 500);
    }

    return $course;
}

function ensure_enrollment(int $userId, int $courseId): void
{
    $stmt = db()->prepare(
        'INSERT OR IGNORE INTO enrollments (user_id, course_id)
         VALUES (:user_id, :course_id)'
    );
    $stmt->execute([
        'user_id' => $userId,
        'course_id' => $courseId,
    ]);
}

function certificate_status(int $userId, int $courseId): array
{
    $pdo = db();

    $classCountStmt = $pdo->prepare('SELECT COUNT(*) FROM course_classes WHERE course_id = :course_id');
    $classCountStmt->execute(['course_id' => $courseId]);
    $classCount = (int) $classCountStmt->fetchColumn();

    $assignmentCountStmt = $pdo->prepare('SELECT COUNT(*) FROM assignments WHERE course_id = :course_id');
    $assignmentCountStmt->execute(['course_id' => $courseId]);
    $assignmentCount = (int) $assignmentCountStmt->fetchColumn();

    $completedClassesStmt = $pdo->prepare(
        'SELECT COUNT(*)
         FROM class_progress cp
         JOIN course_classes cc ON cc.id = cp.course_class_id
         WHERE cp.user_id = :user_id AND cc.course_id = :course_id'
    );
    $completedClassesStmt->execute([
        'user_id' => $userId,
        'course_id' => $courseId,
    ]);
    $completedClasses = (int) $completedClassesStmt->fetchColumn();

    $submittedAssignmentsStmt = $pdo->prepare(
        'SELECT COUNT(*)
         FROM assignment_submissions s
         JOIN assignments a ON a.id = s.assignment_id
         WHERE s.user_id = :user_id AND a.course_id = :course_id'
    );
    $submittedAssignmentsStmt->execute([
        'user_id' => $userId,
        'course_id' => $courseId,
    ]);
    $submittedAssignments = (int) $submittedAssignmentsStmt->fetchColumn();

    $eligible = $classCount > 0
        && $completedClasses === $classCount
        && $assignmentCount > 0
        && $submittedAssignments === $assignmentCount;

    $certificateStmt = $pdo->prepare(
        'SELECT certificate_code, issued_at
         FROM certificates
         WHERE user_id = :user_id AND course_id = :course_id
         LIMIT 1'
    );
    $certificateStmt->execute([
        'user_id' => $userId,
        'course_id' => $courseId,
    ]);
    $certificate = $certificateStmt->fetch();

    if ($eligible && !$certificate) {
        $code = 'KA-CDPA-' . strtoupper(bin2hex(random_bytes(4)));
        $insertStmt = $pdo->prepare(
            'INSERT INTO certificates (user_id, course_id, certificate_code)
             VALUES (:user_id, :course_id, :certificate_code)'
        );
        $insertStmt->execute([
            'user_id' => $userId,
            'course_id' => $courseId,
            'certificate_code' => $code,
        ]);
        $certificate = [
            'certificate_code' => $code,
            'issued_at' => date('Y-m-d H:i:s'),
        ];
    }

    return [
        'eligible' => $eligible,
        'issued' => (bool) $certificate,
        'certificate' => $certificate ?: null,
    ];
}
