<?php

namespace Tests\App\Controllers\View;

use App\Controllers\View\InventoryController;
use CodeIgniter\Test\CIUnitTestCase;
use ReflectionClass;
use ReflectionProperty;

class NormalizedInventoryTestController extends InventoryController
{
    public function __construct()
    {
        // Avoid opening real model/database connections for these regression tests.
    }
}

class InventoryFilterBuilderSpy
{
    public array $whereCalls = [];

    public function where($key, $value = null, ?bool $escape = null): self
    {
        $this->whereCalls[] = [$key, $value, $escape];
        return $this;
    }
}

class InventoryFilterDbStub
{
    public function escape($value): string
    {
        return "'" . str_replace("'", "''", (string) $value) . "'";
    }
}

class InventorySchemaNormalizationTest extends CIUnitTestCase
{
    public function testAffectedRoutesAreRegistered(): void
    {
        $routes = file_get_contents(ROOTPATH . 'app/Config/Routes.php');

        $this->assertStringContainsString("\$routes->get('card', 'View\\FamilyAdminController::card')", $routes);
        $this->assertStringContainsString("\$routes->get('summary-all',                 'View\\InventoryController::summaryAll')", $routes);
        $this->assertStringContainsString("\$routes->get('/',                           'View\\InventoryController::index')", $routes);
        $this->assertStringContainsString("\$routes->get('(classroom|book|office|kitchen)', 'View\\InventoryController::index/\$1')", $routes);
    }

    public function testInventoryPeriodFilterUsesMovementExistsWithoutJoiningDuplicates(): void
    {
        $controller = new NormalizedInventoryTestController();
        $dbProperty = new ReflectionProperty(InventoryController::class, 'db');
        $dbProperty->setAccessible(true);
        $dbProperty->setValue($controller, new InventoryFilterDbStub());

        $builder = new InventoryFilterBuilderSpy();
        $method = (new ReflectionClass(InventoryController::class))->getMethod('applyInventoryMovementPeriodFilter');
        $method->setAccessible(true);

        $method->invoke($controller, $builder, 'i', '2025-2026', 'Fall');

        $this->assertCount(1, $builder->whereCalls);
        [$sql, $value, $escape] = $builder->whereCalls[0];
        $this->assertNull($value);
        $this->assertFalse($escape);
        $this->assertStringContainsString('EXISTS (SELECT 1 FROM inventory_movements m', $sql);
        $this->assertStringContainsString('m.item_id = i.id', $sql);
        $this->assertStringContainsString("m.school_year = '2025-2026'", $sql);
        $this->assertStringContainsString("m.semester = 'Fall'", $sql);
        $this->assertStringNotContainsString('inventory_items.school_year', $sql);
        $this->assertStringNotContainsString('i.school_year', $sql);
    }

    public function testInventoryAllYearsWithoutSemesterDoesNotFilterItems(): void
    {
        $controller = new NormalizedInventoryTestController();
        $dbProperty = new ReflectionProperty(InventoryController::class, 'db');
        $dbProperty->setAccessible(true);
        $dbProperty->setValue($controller, new InventoryFilterDbStub());

        $builder = new InventoryFilterBuilderSpy();
        $method = (new ReflectionClass(InventoryController::class))->getMethod('applyInventoryMovementPeriodFilter');
        $method->setAccessible(true);

        $method->invoke($controller, $builder, 'i', 'All', '');

        $this->assertSame([], $builder->whereCalls);
    }

    public function testPatchedFilesDoNotReferenceRemovedNormalizedColumns(): void
    {
        $familyAdmin = file_get_contents(ROOTPATH . 'app/Controllers/View/FamilyAdminController.php');
        $parent = file_get_contents(ROOTPATH . 'app/Controllers/View/ParentController.php');
        $inventory = file_get_contents(ROOTPATH . 'app/Controllers/View/InventoryController.php');
        $classPreparation = file_get_contents(ROOTPATH . 'app/Controllers/View/ClassPreparationController.php');

        $this->assertStringNotContainsString('emergency_contact_name, relation, cellphone, email, school_year, semester', $familyAdmin);
        $this->assertStringNotContainsString("'school_year'            => \$schoolYear", $parent);
        $this->assertStringNotContainsString("'semester'               => \$semester", $parent);
        $this->assertStringNotContainsString("->where('i.school_year'", $inventory);
        $this->assertStringNotContainsString("->where('ii.school_year'", $classPreparation);
        $this->assertStringNotContainsString("->where('ii.semester'", $classPreparation);
    }
}
