<?php

namespace Tests\App\Controllers\Api;

use App\Controllers\Api\TeacherController;
use App\Models\ConfigurationModel;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\Test\CIUnitTestCase;

class StubUserModel
{
    private ?array $firstResult = null;

    public function select(string $columns): self
    {
        return $this;
    }

    public function join(string $table, string $cond, ?string $type = null): self
    {
        return $this;
    }

    public function whereIn(string $column, array $values): self
    {
        return $this;
    }

    public function groupBy(string $column): self
    {
        return $this;
    }

    public function where(string $column, $value = null): self
    {
        return $this;
    }

    public function first(): ?array
    {
        return $this->firstResult;
    }

    public function setFirstResult(?array $result): void
    {
        $this->firstResult = $result;
    }
}

class StubTeacherClassModel
{
    private array $result = [];

    public function select(string $columns): self
    {
        return $this;
    }

    public function join(string $table, string $cond, ?string $type = null): self
    {
        return $this;
    }

    public function where(string $column, $value = null): self
    {
        return $this;
    }

    public function findAll(): array
    {
        return $this->result;
    }

    public function setResult(array $result): void
    {
        $this->result = $result;
    }
}

class TestableTeacherController extends TeacherController
{
    private array $overridePagination = [];

    public function __construct()
    {
        // Prevent the real controller bootstrapping from hitting the database.
    }

    public function setModels($userModel, $teacherClassModel, ConfigurationModel $configModel): void
    {
        $this->userModel = $userModel;
        $this->teacherClassModel = $teacherClassModel;
        $this->configModel = $configModel;
    }

    public function setPaginatedResult(array $result): void
    {
        $this->overridePagination = $result;
    }

    protected function paginate($source, int $page = 1, int $perPage = 20): array
    {
        if (!empty($this->overridePagination)) {
            return $this->overridePagination;
        }

        return parent::paginate($source, $page, $perPage);
    }
}

class TeacherControllerTest extends CIUnitTestCase
{
    private TestableTeacherController $controller;
    private $userModel;
    private $teacherClassModel;
    private $configModel;

    protected function setUp(): void
    {
        parent::setUp();

        $this->userModel = new StubUserModel();
        $this->teacherClassModel = new StubTeacherClassModel();
        $this->configModel = $this->createMock(ConfigurationModel::class);

        $this->configModel->method('getConfig')->willReturnMap([
            ['school_year', '2024-2025'],
            ['semester', 'Spring'],
        ]);

        $this->controller = new TestableTeacherController();
        $request = $this->createMock(IncomingRequest::class);
        $request->method('getGet')->willReturn(null);
        $this->controller->setRequest($request);
        $this->controller->setModels($this->userModel, $this->teacherClassModel, $this->configModel);
    }

    public function testIndexSkipsSensitiveFieldsAndAddsAssignments()
    {
        $paginatedPayload = [
            'data' => [
                ['id' => 5, 'email' => 'vera@example.com', 'password' => 'secret', 'token' => 'x'],
            ],
            'pagination' => ['current_page' => 1, 'per_page' => 20, 'total' => 1, 'total_pages' => 1],
        ];

        $assignments = [['class_section_id' => 7, 'school_year' => '2024-2025', 'semester' => 'Spring']];
        $this->teacherClassModel->setResult($assignments);

        $this->controller->setPaginatedResult($paginatedPayload);

        $response = $this->controller->index();

        $this->assertTrue($response['status']);
        $this->assertSame('Teachers retrieved successfully', $response['message']);

        $teachers = $response['data']['data'];
        $this->assertCount(1, $teachers);
        $teacher = $teachers[0];

        $this->assertArrayNotHasKey('password', $teacher);
        $this->assertArrayNotHasKey('token', $teacher);
        $this->assertSame($assignments, $teacher['class_assignments']);
    }

    public function testShowReturnsTeacherWithAssignments()
    {
        $teacherRow = ['id' => 8, 'email' => 'nora@example.com', 'password' => 'secret', 'token' => 'abc'];
        $this->userModel->setFirstResult($teacherRow);

        $assignments = [['class_section_id' => 9]];
        $this->teacherClassModel->setResult($assignments);

        $response = $this->controller->show(8);

        $this->assertTrue($response['status']);
        $this->assertSame('Teacher retrieved successfully', $response['message']);

        $teacher = $response['data'];
        $this->assertArrayNotHasKey('password', $teacher);
        $this->assertArrayNotHasKey('token', $teacher);
        $this->assertSame($assignments, $teacher['class_assignments']);
    }

    public function testShowReturns404WhenTeacherMissing()
    {
        $this->userModel->setFirstResult(null);

        $response = $this->controller->show(99);

        $this->assertFalse($response['status']);
        $this->assertSame(404, $response['code']);
        $this->assertSame('Teacher not found', $response['message']);
    }

    public function testGetClassesReturnsAssignments()
    {
        $assignments = [['class_section_id' => 3]];
        $this->teacherClassModel->setResult($assignments);

        $response = $this->controller->getClasses(4);

        $this->assertTrue($response['status']);
        $this->assertSame('Teacher classes retrieved successfully', $response['message']);
        $this->assertSame($assignments, $response['data']);
    }
}
