'use strict';

const fs = require('fs');
const path = require('path');

const root = __dirname;
const read = (relativePath) => fs.readFileSync(path.join(root, relativePath), 'utf8');
const results = [];
let failures = 0;

function check(name, condition, detail = '') {
    const passed = Boolean(condition);
    if (!passed) failures += 1;
    results.push({ status: passed ? 'PASS' : 'FAIL', name, detail });
}

function extractInputTag(html, name) {
    const match = html.match(new RegExp(`<input\\b[^>]*\\bname=["']${name}["'][^>]*>`, 'i'));
    return match ? match[0] : '';
}

const header = read('app/header.php');
const footer = read('app/footer.php');
const create = read('ticket_create.php');
const view = read('ticket_view.php');
const appJs = read('assets/js/app.js');
const css = read('assets/css/style.css');
const htaccess = read('.htaccess');
const page404 = read('404.php');
const logout = read('logout.php');
const database = read('database.sql');
const dump = read('sosmthhg_infratest.sql');

const issueInput = extractInputTag(create, 'issue_location');
const inventoryInput = extractInputTag(create, 'asset_inventory_no');
const descriptionMatch = create.match(/<textarea\b[^>]*\bname=["']description["'][^>]*>/i);
const descriptionInput = descriptionMatch ? descriptionMatch[0] : '';

check('Mobilni meni koristi postojeću bezbednu logout rutu',
    header.includes("logout.php?csrf=") && header.includes('rawurlencode(csrf_token())') && header.includes('>Odjava</a>'));
check('Logout skripta proverava postojeći CSRF token',
    logout.includes('csrf_token_is_valid'));
check('Logout skripta vraća korisnika na prijavu',
    logout.includes("$redirectUrl = url('login.php')") && logout.includes("header('Location: ' . $redirectUrl)"));
check('Mobilni dropdown ima ograničenu visinu i sopstveni skrol linkova',
    css.includes('max-height: calc(100dvh - var(--topbar) - 18px)') &&
    css.includes('.user-menu-links') && css.includes('overflow-y: auto'));
check('Mobilna Odjava eksplicitno nadjačava staro skrivanje button-light dugmeta',
    css.includes('.topbar-akcije .user-dropdown-footer .button-light') && css.includes('display: inline-flex'));
check('Desktop izgled nije menjan globalnom redefinicijom user dropdown-a',
    /@media \(max-width: 900px\)[\s\S]*?\.user-dropdown[\s\S]*?z-index: 400;/.test(css));

check('404 stranica eksplicitno vraća HTTP 404', page404.includes('http_response_code(404)'));
check('404 stranica sadrži tačno zahtevanu glavnu poruku', page404.includes('Stranica koju tražite ne postoji.'));
check('404 stranica sadrži tačno zahtevano objašnjenje',
    page404.includes('Moguće je da je stranica uklonjena, premeštena ili da adresa nije pravilno uneta.'));
check('404 povratna ruta zavisi od prijavljenog korisnika',
    page404.includes("$returnUrl = $user ? 'dashboard.php' : 'login.php';"));
check('404 stranica koristi postojeći header/footer i lokalnu CSS ilustraciju',
    page404.includes("app/header.php") && page404.includes("app/footer.php") &&
    page404.includes('error-illustration') && css.includes('.error-illustration'));
check('Apache catch-all preusmerava samo nepostojeće fajlove i direktorijume',
    htaccess.includes('RewriteCond %{REQUEST_FILENAME} !-f') &&
    htaccess.includes('RewriteCond %{REQUEST_FILENAME} !-d') &&
    htaccess.includes('RewriteRule ^ 404.php [L]'));
check('Nedostupan ili neovlašćen tiket koristi generičku 404 stranicu',
    view.includes("require __DIR__ . '/404.php';"));

check('Polje Mesto kvara postoji i nema required atribut',
    issueInput !== '' && !/\brequired\b/i.test(issueInput), issueInput);
check('Serverska validacija mesta kvara dozvoljava praznu vrednost',
    create.includes("$issueLocation !== '' &&") &&
    create.includes("$issueLocation !== '' ? $issueLocation : null"));
check('Naslov tiketa ne dobija prazan separator kada mesto kvara nije uneto',
    create.includes("$issueLocation !== '' ? $category . ' — ' . $issueLocation : $category"));
check('SQL šema dozvoljava NULL za mesto kvara u obe baze',
    /issue_location\s+VARCHAR\(190\)\s+NULL/i.test(database) &&
    /`issue_location`\s+varchar\(190\)\s+DEFAULT NULL/i.test(dump));

check('Inventarski broj postoji i nema required atribut',
    inventoryInput !== '' && !/\brequired\b/i.test(inventoryInput), inventoryInput);
check('Serverski upis inventarskog broja dozvoljava NULL',
    create.includes("$assetInventoryNo !== '' ? $assetInventoryNo : null"));
check('SQL šema dozvoljava NULL inventarski broj u obe baze',
    /asset_inventory_no\s+VARCHAR\(120\)\s+NULL/i.test(database) &&
    /`asset_inventory_no`\s+varchar\(120\)\s+DEFAULT NULL/i.test(dump));
check('Automatsko popunjavanje inventarskog broja iz opreme je zadržano',
    create.includes("$_GET['equipment_id']") &&
    create.includes('SELECT inventory_no FROM equipment') &&
    create.includes("$defaultAssetInventoryNo = trim((string)($prefillEquipment['inventory_no'] ?? ''))") &&
    create.includes("$_POST['asset_inventory_no'] ?? $defaultAssetInventoryNo"));

check('Opis problema ostaje required polje',
    descriptionInput !== '' && /\brequired\b/i.test(descriptionInput), descriptionInput);
check('Klijentska poruka za prazan opis je tačna',
    appJs.includes("const missingDescriptionMessage = 'Molimo unesite opis problema.';"));
check('Klijentska validacija koristi setCustomValidity i resetuje poruku pri unosu',
    appJs.includes("descriptionInput.setCustomValidity(missingDescriptionMessage)") &&
    appJs.includes("descriptionInput.setCustomValidity('')") &&
    appJs.includes("descriptionInput.addEventListener('input'"));
check('Whitespace-only opis je blokiran pre slanja forme',
    appJs.includes("descriptionInput.value.trim() === ''") && appJs.includes('event.preventDefault()'));
check('Serverska poruka za prazan opis je tačna',
    create.includes("$errors[] = 'Molimo unesite opis problema.';"));
check('Serverska validacija kratkog opisa ostaje aktivna',
    create.includes("Opis problema mora imati najmanje 10 karaktera."));
check('Unete vrednosti forme ostaju u poljima nakon serverske greške',
    create.includes("$_POST['issue_location'] ?? ''") &&
    create.includes("$_POST['asset_inventory_no'] ?? $defaultAssetInventoryNo") &&
    create.includes("$_POST['description'] ?? ''"));

check('CSS i JavaScript koriste aktuelnu cache verziju',
    header.includes('style.css') && header.includes('app.js') &&
    (header.match(/\?v=3\.21\.0/g) || []).length >= 2);
check('Footer datoteka postoji i ostaje uključiva', footer.length > 0);
check('CSS blokovi imaju uparen broj vitičastih zagrada',
    (css.match(/{/g) || []).length === (css.match(/}/g) || []).length,
    `${(css.match(/{/g) || []).length}/${(css.match(/}/g) || []).length}`);

for (const result of results) {
    console.log(`${result.status.padEnd(4)} | ${result.name}${result.detail ? ` | ${result.detail}` : ''}`);
}
console.log(`\nUKUPNO: ${results.length - failures}/${results.length} PASS`);
process.exitCode = failures === 0 ? 0 : 1;
