<?php

namespace Tests\App\Controllers\Api;

use App\Controllers\Api\FamilyController;
use App\Models\FamilyGuardianModel;
use App\Models\FamilyModel;
use App\Models\FamilyStudentModel;
use CodeIgniter\Test\CIUnitTestCase;

class TestableFamilyController extends FamilyController
{
    private array $overridePagination = [];

    public function setModels(FamilyModel $familyModel, FamilyStudentModel $familyStudentModel, FamilyGuardianModel $familyGuardianModel): void
    {
        $this->familyModel = $familyModel;
        $this->familyStudentModel = $familyStudentModel;
        $this->familyGuardianModel = $familyGuardianModel;
    }

    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 FamilyControllerTest extends CIUnitTestCase
{
    private $controller;
    private $familyModel;
    private $studentModel;
    private $guardianModel;

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

        $this->familyModel = $this->createMock(FamilyModel::class);
        $this->studentModel = $this->createMock(FamilyStudentModel::class);
        $this->guardianModel = $this->createMock(FamilyGuardianModel::class);

        $this->controller = new TestableFamilyController();
        $this->controller->setModels($this->familyModel, $this->studentModel, $this->guardianModel);
    }

    public function testGetGuardiansReturnsDataWhenFamilyExists()
    {
        $this->familyModel->method('find')->with(5)->willReturn(['id' => 5]);
        $this->guardianModel->method('where')->willReturnSelf();
        $this->guardianModel->method('findAll')->willReturn([
            ['id' => 11, 'cellphone' => '555-0101'],
        ]);

        $response = $this->controller->getGuardians(5);
        $this->assertTrue($response['status']);
        $this->assertCount(1, $response['data']);
    }

    public function testGetGuardiansReturnsErrorWhenFamilyMissing()
    {
        $this->familyModel->method('find')->with(3)->willReturn(null);

        $response = $this->controller->getGuardians(3);
        $this->assertFalse($response['status']);
        $this->assertEquals(404, $response['code']);
    }

    public function testGetByStudentWrapsStudentsAndGuardians()
    {
        $this->studentModel->method('where')->willReturnSelf();
        $this->studentModel->method('findColumn')->willReturn([10]);
        $this->familyModel->method('whereIn')->willReturnSelf();
        $this->familyModel->method('findAll')->willReturn([
            ['id' => 10, 'family_name' => 'Main Family'],
        ]);

        $this->studentModel->method('findAll')->willReturn([
            ['id' => 222, 'firstname' => 'Amina'],
        ]);
        $this->guardianModel->method('where')->willReturnSelf();
        $this->guardianModel->method('findAll')->willReturn([
            ['id' => 33, 'firstname' => 'Derrell'],
        ]);

        $response = $this->controller->getByStudent(42);
        $this->assertTrue($response['status']);
        $this->assertEquals('Families retrieved successfully', $response['message']);
        $this->assertNotEmpty($response['data']);
        $this->assertArrayHasKey('students', $response['data'][0]);
    }

    public function testIndexUsesPaginatedResult()
    {
        $paginatedPayload = [
            'data' => [
                ['id' => 1, 'family_name' => 'Alver Family'],
            ],
            'pagination' => ['current_page' => 1, 'per_page' => 20, 'total' => 1, 'total_pages' => 1],
        ];
        $this->controller->setPaginatedResult($paginatedPayload);

        $response = $this->controller->index();
        $this->assertTrue($response['status']);
        $this->assertSame($paginatedPayload, $response['data']);
    }

    public function testShowReturnsFamily()
    {
        $this->familyModel->method('find')->with(17)->willReturn(['id' => 17, 'family_name' => 'Mansour']);
        $this->studentModel->method('where')->willReturnSelf();
        $this->studentModel->method('findAll')->willReturn([]);
        $this->guardianModel->method('where')->willReturnSelf();
        $this->guardianModel->method('findAll')->willReturn([]);

        $response = $this->controller->show(17);
        $this->assertTrue($response['status']);
        $this->assertEquals('Family retrieved successfully', $response['message']);
    }
}
