<?php

namespace Tests\App\Controllers\Api;

use App\Controllers\Api\ContactController;
use App\Controllers\View\EmailController;
use CodeIgniter\Test\CIUnitTestCase;
use Config\Services;

class FakeJsonRequest
{
    public function __construct(private readonly ?array $payload)
    {
    }

    public function getJSON(bool $assoc = false): ?array
    {
        return $this->payload;
    }
}

class StubEmailController extends EmailController
{
    public function __construct(private readonly bool $result)
    {
    }

    public function sendEmail(
        string $recipient,
        string $subject,
        string $htmlMessage,
        ?string $profile = null,
        ?string $replyToEmail = null,
        ?string $replyToName = null,
        array $attachments = []
    ): bool {
        return $this->result;
    }
}

class TestableContactController extends ContactController
{
    private ?EmailController $emailController = null;

    public function __construct()
    {
        // Skip the parent bootstrap so we control dependencies manually.
    }

    public function setEmailController(EmailController $emailController): void
    {
        $this->emailController = $emailController;
    }

    protected function createEmailController(): EmailController
    {
        return $this->emailController ?? parent::createEmailController();
    }
}

class ContactControllerTest extends CIUnitTestCase
{
    private TestableContactController $controller;

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

        Services::resetSingle('validation');

        $this->controller = new TestableContactController();
    }

    public function testSubmitReturnsErrorWhenJsonMissing()
    {
        $this->setRequestPayload(null);

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

        $this->assertFalse($response['status']);
        $this->assertSame(400, $response['code']);
        $this->assertSame('Invalid request data', $response['message']);
    }

    public function testSubmitReturnsValidationErrors()
    {
        $this->setRequestPayload([
            'name' => 'Al',
            'email' => 'invalid',
            'subject' => 'Hi',
            'message' => 'short',
        ]);

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

        $this->assertFalse($response['status']);
        $this->assertSame(422, $response['code']);
        $this->assertSame('Validation failed', $response['message']);
        $this->assertArrayHasKey('errors', $response);
        $this->assertNotEmpty($response['errors']);
    }

    public function testSubmitReturnsSuccessWhenEmailSent()
    {
        $this->controller->setEmailController(new StubEmailController(true));
        $this->setRequestPayload($this->validPayload());

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

        $this->assertTrue($response['status']);
        $this->assertSame('Thank you for contacting us! We will get back to you soon.', $response['message']);
        $this->assertNull($response['data']);
    }

    public function testSubmitReturnsErrorWhenEmailFails()
    {
        $this->controller->setEmailController(new StubEmailController(false));
        $this->setRequestPayload($this->validPayload());

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

        $this->assertFalse($response['status']);
        $this->assertSame(500, $response['code']);
        $this->assertSame('There was an error sending your message. Please try again later.', $response['message']);
    }

    private function setRequestPayload(?array $payload): void
    {
        $request = new FakeJsonRequest($payload);
        self::setPrivateProperty($this->controller, 'request', $request);
    }

    private function validPayload(): array
    {
        return [
            'name' => 'Alia Ahmed',
            'email' => 'alia@alrahmaisgl.org',
            'subject' => 'Support request',
            'message' => str_repeat('Please assist. ', 5),
        ];
    }
}
