<?php

namespace Tests\Feature;

use CodeIgniter\Test\FeatureTestTrait;
use CodeIgniter\Test\CIUnitTestCase;

class UniformShowTest extends CIUnitTestCase
{
    use FeatureTestTrait;

    protected $endpoint = 'api';
    protected $token;

    protected function setUp(): void
    {
        parent::setUp();
        // Generate Token
        $key = getenv('JWT_SECRET') ?: 'my-secret-key'; // Fallback if env not loaded in test
        $payload = [
            'iss' => 'localhost',
            'aud' => 'localhost',
            'iat' => time(),
            'nbf' => time(),
            'exp' => time() + 3600,
            'uid' => 1,
            'email' => 'admin@admin.com'
        ];
        $this->token = \Firebase\JWT\JWT::encode($payload, $key, 'HS256');
    }
    
    // Override get to inject cookie header
    public function get(string $path, array $options = []) {
        $this->withHeaders(['Cookie' => 'token=' . $this->token]);
        return $this->call('get', $path, $options);
    }

    /**
     * Test that show endpoints return a single object (associative array) in 'data' when found.
     */
    public function testShowEndpointsReturnObjectWhenFound()
    {
        // representative endpoints.
        $endpoints = [
            'api/location',
            'api/organization/site',
            'api/organization/account',
            'api/patient',
            'api/tests',
            'api/specimen/containerdef',
            'api/contact',
        ];

        foreach ($endpoints as $url) {
            // We first check index to get a valid ID if possible
            $indexResult = $this->get($url);
            $indexBody = json_decode($indexResult->response()->getBody(), true);
            
            $id = 1; // logical default
            if (isset($indexBody['data']) && is_array($indexBody['data']) && !empty($indexBody['data'])) {
                $firstItem = $indexBody['data'][0];
                // Try to guess ID key
                $idKeys = ['LocationID', 'SiteID', 'AccountID', 'InternalPID', 'TestSiteID', 'ConDefID', 'ContactID', 'VID', 'id'];
                foreach ($idKeys as $key) {
                    if (isset($firstItem[$key])) {
                        $id = $firstItem[$key];
                        break;
                    }
                }
            }

            $showUrl = $url . '/' . $id;
            $result = $this->get($showUrl);
            $body = json_decode($result->response()->getBody(), true);
            
            if ($result->response()->getStatusCode() === 200 && isset($body['data']) && $body['data'] !== null) {
                $this->assertTrue(
                    $this->is_assoc($body['data']), 
                    "Endpoint $showUrl should return an object in 'data', but got a sequential array or empty array. Body: " . $result->response()->getBody()
                );
            }
        }
    }

    public function testShowEndpointsReturnNullWhenNotFound()
    {
        $endpoints = [
            'api/location/9999999',
            'api/organization/site/9999999',
            'api/patient/9999999',
        ];

        foreach ($endpoints as $url) {
            $result = $this->get($url);
            $result->assertStatus(200);
            $body = json_decode($result->response()->getBody(), true);
            
            $this->assertArrayHasKey('data', $body, "Endpoint $url missing 'data' key. Body: " . $result->response()->getBody());
            $this->assertNull($body['data'], "Endpoint $url should return null in 'data' when not found. Body: " . $result->response()->getBody());
        }
    }

    /**
     * Helper to check if array is associative.
     */
    private function is_assoc(array $arr)
    {
        if (array() === $arr) return false;
        return array_keys($arr) !== range(0, count($arr) - 1);
    }
}
