<?php

namespace Tests\Unit\Http\Controllers\Api;

use App\Http\Controllers\Api\Attendance\AttendanceCommentTemplateController;
use App\Http\Requests\AttendanceCommentTemplate\StoreAttendanceCommentTemplateRequest;
use App\Http\Requests\AttendanceCommentTemplate\UpdateAttendanceCommentTemplateRequest;
use App\Services\AttendanceCommentTemplateService;
use Illuminate\Http\Request;
use Mockery;
use Tests\TestCase;

class AttendanceCommentTemplateControllerTest extends TestCase
{
    protected function tearDown(): void
    {
        Mockery::close();
        parent::tearDown();
    }

    public function test_index_returns_success_json(): void
    {
        $service = Mockery::mock(AttendanceCommentTemplateService::class);
        $service->shouldReceive('list')
            ->once()
            ->with(false)
            ->andReturn([
                ['id' => 1, 'min_score' => 0, 'max_score' => 59, 'template_text' => 'Needs improvement', 'is_active' => true],
            ]);

        $controller = new AttendanceCommentTemplateController($service);

        $request = Request::create('/api/attendance-comment-templates', 'GET');

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

        $this->assertSame(200, $response->getStatusCode());

        $data = $response->getData(true);
        $this->assertSame('success', $data['status']);
        $this->assertCount(1, $data['data']);
        $this->assertSame(1, $data['data'][0]['id']);
    }

    public function test_index_passes_active_only_true(): void
    {
        $service = Mockery::mock(AttendanceCommentTemplateService::class);
        $service->shouldReceive('list')
            ->once()
            ->with(true)
            ->andReturn([]);

        $controller = new AttendanceCommentTemplateController($service);

        $request = Request::create('/api/attendance-comment-templates?active_only=1', 'GET');

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

        $this->assertSame(200, $response->getStatusCode());
        $data = $response->getData(true);
        $this->assertSame([], $data['data']);
    }

    public function test_show_returns_template(): void
    {
        $service = Mockery::mock(AttendanceCommentTemplateService::class);
        $service->shouldReceive('findOrFail')
            ->once()
            ->with(5)
            ->andReturn([
                'id' => 5,
                'min_score' => 60,
                'max_score' => 79,
                'template_text' => 'Good effort',
                'is_active' => true,
            ]);

        $controller = new AttendanceCommentTemplateController($service);

        $response = $controller->show(5);

        $this->assertSame(200, $response->getStatusCode());
        $data = $response->getData(true);

        $this->assertSame('success', $data['status']);
        $this->assertSame(5, $data['data']['id']);
    }

    public function test_store_returns_created_response(): void
    {
        $payload = [
            'min_score' => 80,
            'max_score' => 100,
            'template_text' => 'Excellent attendance',
            'is_active' => true,
        ];

        $service = Mockery::mock(AttendanceCommentTemplateService::class);
        $service->shouldReceive('create')
            ->once()
            ->with($payload)
            ->andReturn(array_merge(['id' => 10], $payload));

        $controller = new AttendanceCommentTemplateController($service);

        $request = Mockery::mock(StoreAttendanceCommentTemplateRequest::class);
        $request->shouldReceive('validated')->once()->andReturn($payload);

        $response = $controller->store($request);

        $this->assertSame(201, $response->getStatusCode());
        $data = $response->getData(true);

        $this->assertSame('success', $data['status']);
        $this->assertSame('Template created successfully.', $data['message']);
        $this->assertSame(10, $data['data']['id']);
    }

    public function test_update_returns_success_response(): void
    {
        $payload = [
            'template_text' => 'Updated text',
            'is_active' => false,
        ];

        $service = Mockery::mock(AttendanceCommentTemplateService::class);
        $service->shouldReceive('update')
            ->once()
            ->with(7, $payload)
            ->andReturn([
                'id' => 7,
                'min_score' => 70,
                'max_score' => 79,
                'template_text' => 'Updated text',
                'is_active' => false,
            ]);

        $controller = new AttendanceCommentTemplateController($service);

        $request = Mockery::mock(UpdateAttendanceCommentTemplateRequest::class);
        $request->shouldReceive('validated')->once()->andReturn($payload);

        $response = $controller->update($request, 7);

        $this->assertSame(200, $response->getStatusCode());
        $data = $response->getData(true);

        $this->assertSame('success', $data['status']);
        $this->assertSame(7, $data['data']['id']);
        $this->assertFalse($data['data']['is_active']);
    }

    public function test_destroy_returns_success_response(): void
    {
        $service = Mockery::mock(AttendanceCommentTemplateService::class);
        $service->shouldReceive('delete')->once()->with(12);

        $controller = new AttendanceCommentTemplateController($service);

        $response = $controller->destroy(12);

        $this->assertSame(200, $response->getStatusCode());
        $data = $response->getData(true);

        $this->assertSame('success', $data['status']);
        $this->assertSame('Template deleted successfully.', $data['message']);
    }

    public function test_list_data_returns_templates_key(): void
    {
        $service = Mockery::mock(AttendanceCommentTemplateService::class);
        $service->shouldReceive('list')
            ->once()
            ->with(false)
            ->andReturn([
                ['id' => 1, 'min_score' => 0, 'max_score' => 49, 'template_text' => 'Low', 'is_active' => true],
            ]);

        $controller = new AttendanceCommentTemplateController($service);

        $request = Request::create('/api/attendance-comment-templates/list-data', 'GET');

        $response = $controller->listData($request);

        $this->assertSame(200, $response->getStatusCode());
        $data = $response->getData(true);

        $this->assertArrayHasKey('templates', $data);
        $this->assertCount(1, $data['templates']);
    }
}