<?php
declare(strict_types=1);

/**
 * EnglishSpeak - Teacher Units
 * File: teacher/units/store.php
 *
 * Creates a Unit under one Book.
 */

require __DIR__ . '/../partials/auth.php';
require_once __DIR__ . '/../../config/database.php';

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    header('Location: index.php');
    exit;
}

$pdo = getDbConnection();

$bookId = max(0, (int)($_POST['book_id'] ?? 0));
$levelId = max(0, (int)($_POST['level_id'] ?? 0));
$unitNumber = trim((string)($_POST['unit_number'] ?? ''));
$title = trim((string)($_POST['title'] ?? ''));
$description = trim((string)($_POST['description'] ?? ''));
$requiredXp = max(0, (int)($_POST['required_xp'] ?? 0));
$sortOrder = max(0, (int)($_POST['sort_order'] ?? 0));
$status = (string)($_POST['status'] ?? 'active');

if (!in_array($status, ['active', 'inactive'], true)) {
    $status = 'active';
}

$old = [
    'book_id' => $bookId,
    'level_id' => $levelId,
    'unit_number' => $unitNumber,
    'title' => $title,
    'description' => $description,
    'required_xp' => $requiredXp,
    'sort_order' => $sortOrder,
    'status' => $status,
];

$errors = [];

// Validate Book and Level.
if ($bookId <= 0) {
    $errors[] = 'Please select a Book.';
}

if ($levelId <= 0) {
    $errors[] = 'Please select a Level.';
}

if ($bookId > 0 && $levelId > 0) {
    $levelStmt = $pdo->prepare(
        "SELECT l.id
         FROM levels l
         INNER JOIN books b ON b.id = l.book_id
         WHERE l.id = ?
           AND l.book_id = ?
           AND l.status = 'active'
           AND b.status = 'active'
         LIMIT 1"
    );
    $levelStmt->execute([$levelId, $bookId]);

    if (!$levelStmt->fetchColumn()) {
        $errors[] = 'The selected Level is not available for this Book.';
    }
}

// Validate text.
if ($unitNumber === '') {
    $errors[] = 'Unit Number is required.';
} elseif (mb_strlen($unitNumber) > 20) {
    $errors[] = 'Unit Number must not exceed 20 characters.';
}

if ($title === '') {
    $errors[] = 'Unit Title is required.';
} elseif (mb_strlen($title) > 150) {
    $errors[] = 'Unit Title must not exceed 150 characters.';
}

if (mb_strlen($description) > 5000) {
    $errors[] = 'Description is too long.';
}

// Enforce unique Unit Number inside one Book.
if ($bookId > 0 && $unitNumber !== '') {
    $duplicateStmt = $pdo->prepare(
        "SELECT id
         FROM units
         WHERE level_id = ?
           AND LOWER(TRIM(unit_number)) = LOWER(TRIM(?))
         LIMIT 1"
    );
    $duplicateStmt->execute([$levelId, $unitNumber]);

    if ($duplicateStmt->fetchColumn()) {
        $errors[] = 'This Unit Number already exists in the selected Book.';
    }
}

/**
 * Validate and store the optional thumbnail.
 *
 * @return string|null Relative project path for database storage.
 */
function storeUnitThumbnail(array &$errors): ?string
{
    if (
        !isset($_FILES['thumbnail'])
        || !is_array($_FILES['thumbnail'])
        || (int)($_FILES['thumbnail']['error'] ?? UPLOAD_ERR_NO_FILE) === UPLOAD_ERR_NO_FILE
    ) {
        return null;
    }

    $file = $_FILES['thumbnail'];
    $errorCode = (int)($file['error'] ?? UPLOAD_ERR_NO_FILE);

    if ($errorCode !== UPLOAD_ERR_OK) {
        $errors[] = 'The thumbnail could not be uploaded.';
        return null;
    }

    $tmpPath = (string)($file['tmp_name'] ?? '');
    $size = (int)($file['size'] ?? 0);

    if ($tmpPath === '' || !is_uploaded_file($tmpPath)) {
        $errors[] = 'The uploaded thumbnail is invalid.';
        return null;
    }

    // Maximum 3 MB.
    if ($size <= 0 || $size > 3 * 1024 * 1024) {
        $errors[] = 'Thumbnail must be smaller than 3 MB.';
        return null;
    }

    $mime = '';
    if (function_exists('finfo_open')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        if ($finfo !== false) {
            $mime = (string)finfo_file($finfo, $tmpPath);
            finfo_close($finfo);
        }
    }

    $allowed = [
        'image/jpeg' => 'jpg',
        'image/png' => 'png',
        'image/webp' => 'webp',
    ];

    if (!isset($allowed[$mime])) {
        $errors[] = 'Thumbnail must be a JPG, PNG or WEBP image.';
        return null;
    }

    $projectRoot = dirname(__DIR__, 2);
    $relativeDir = 'uploads/units';
    $absoluteDir = $projectRoot . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . 'units';

    if (!is_dir($absoluteDir) && !mkdir($absoluteDir, 0775, true) && !is_dir($absoluteDir)) {
        $errors[] = 'The Unit upload folder could not be created.';
        return null;
    }

    try {
        $random = bin2hex(random_bytes(8));
    } catch (Throwable $e) {
        $random = str_replace('.', '', uniqid('', true));
    }

    $filename = 'unit-' . date('Ymd-His') . '-' . $random . '.' . $allowed[$mime];
    $absolutePath = $absoluteDir . DIRECTORY_SEPARATOR . $filename;

    if (!move_uploaded_file($tmpPath, $absolutePath)) {
        $errors[] = 'The thumbnail could not be saved.';
        return null;
    }

    return $relativeDir . '/' . $filename;
}

$thumbnail = null;

if ($errors === []) {
    $thumbnail = storeUnitThumbnail($errors);
}

if ($errors !== []) {
    $_SESSION['units_old'] = $old;
    $_SESSION['units_errors'] = $errors;

    $query = [];
    if ($bookId > 0) {
        $query['book_id'] = $bookId;
    }
    if ($levelId > 0) {
        $query['level_id'] = $levelId;
    }

    header(
        'Location: create.php' .
        ($query !== [] ? '?' . http_build_query($query) : '')
    );
    exit;
}

try {
    $columnsStmt = $pdo->query('SHOW COLUMNS FROM units');
    $columnRows = $columnsStmt->fetchAll(PDO::FETCH_ASSOC);
    $unitColumns = array_column($columnRows, null, 'Field');

    $sortStmt = $pdo->prepare(
        'SELECT COALESCE(MAX(sort_order), 0) + 1
         FROM units
         WHERE level_id = ?'
    );
    $sortStmt->execute([$levelId]);

    if ($sortOrder <= 0) {
        $sortOrder = max(1, (int)$sortStmt->fetchColumn());
    }

    $slugBase = strtolower(
        trim(
            (string)preg_replace(
                '/[^a-zA-Z0-9]+/',
                '-',
                $unitNumber . '-' . $title
            ),
            '-'
        )
    );

    if ($slugBase === '') {
        $slugBase = 'unit-' . time();
    }

    $data = [
        'book_id' => $bookId,
        'level_id' => $levelId,
        'unit_number' => $unitNumber,
        'number' => $unitNumber,
        'title' => $title,
        'name' => $title,
        'unit_name' => $title,
        'slug' => $slugBase,
        'thumbnail' => $thumbnail,
        'description' => $description !== '' ? $description : null,
        'required_xp' => $requiredXp,
        'sort_order' => $sortOrder,
        'order_index' => $sortOrder,
        'status' => $status,
        'is_active' => $status === 'active' ? 1 : 0,
    ];

    $fields = [];
    $placeholders = [];
    $params = [];

    foreach ($data as $field => $value) {
        if (!isset($unitColumns[$field])) {
            continue;
        }

        $fields[] = "`{$field}`";
        $placeholders[] = '?';
        $params[] = $value;
    }

    if (isset($unitColumns['created_at'])) {
        $fields[] = '`created_at`';
        $placeholders[] = 'NOW()';
    }

    if (isset($unitColumns['updated_at'])) {
        $fields[] = '`updated_at`';
        $placeholders[] = 'NOW()';
    }

    if ($fields === []) {
        throw new RuntimeException('No supported Unit columns were found.');
    }

    $stmt = $pdo->prepare(
        'INSERT INTO units (' . implode(', ', $fields) . ')
         VALUES (' . implode(', ', $placeholders) . ')'
    );
    $stmt->execute($params);

    $newUnitId = (int)$pdo->lastInsertId();

    $_SESSION['units_message'] = 'Unit created successfully.';
    $_SESSION['units_message_type'] = 'success';

    header(
        'Location: ../books/index.php?book_id=' . $bookId .
        '&level_id=' . $levelId .
        '&unit_id=' . $newUnitId
    );
    exit;
} catch (Throwable $e) {
    error_log('[EnglishSpeak units/store] ' . $e->getMessage());

    // Remove an uploaded file if the database insert failed.
    if ($thumbnail !== null) {
        $absoluteThumbnail = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR
            . str_replace('/', DIRECTORY_SEPARATOR, $thumbnail);

        if (is_file($absoluteThumbnail)) {
            @unlink($absoluteThumbnail);
        }
    }

    $_SESSION['units_old'] = $old;

    if ($e instanceof PDOException && (string)$e->getCode() === '23000') {
        $_SESSION['units_errors'] = [
            'This Unit Number already exists in the selected Book.',
        ];
    } else {
        $_SESSION['units_errors'] = [
            'Could not create the Unit. Please try again.',
        ];
    }

    header(
        'Location: create.php?book_id=' . $bookId .
        '&level_id=' . $levelId
    );
    exit;
}
