<?php

namespace Tests\Feature;

use App\Models\Accounts\LinhasDoTempo\HistoricalPoint;
use App\Models\Accounts\LinhasDoTempo\Note;
use App\Models\Accounts\LinhasDoTempo\Timeline;
use App\Models\Permissao;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Tests\TestCase;

class LinhasDoTempoTest extends TestCase {

    use DatabaseTransactions;

    /**
     * Cria usuário com permissão do módulo (requer estrutura no banco).
     */
    private function seedUserWithLinhasPermissao(): ?User {
        $structureId = \DB::table('structures')->value('id');
        if (! $structureId) {
            return null;
        }

        $suffix = Str::lower(Str::random(8));
        $user = User::query()->create([
            'structure_id' => $structureId,
            'firstName' => 'Teste',
            'lastName' => 'Linhas',
            'cpf' => str_pad((string) random_int(10000000000, 99999999999), 11, '0', STR_PAD_LEFT),
            'matriculation' => 'LT-' . $suffix,
            'phoneNumber' => '21999999999',
            'email' => 'lt_' . $suffix . '@example.com',
            'password' => Hash::make('password'),
            'status' => 'ATIVADO',
            'isPasswordDefault' => 0,
        ]);

        Permissao::query()->create([
            'user_id' => $user->id,
            'permissao' => 'GERENCIADOR_DE_LINHAS_DO_TEMPO',
            'visualizar' => 1,
            'adicionar' => 1,
            'editar' => 1,
            'excluir' => 1,
            'status' => 'ATIVADO',
        ]);

        return $user->fresh();
    }

    public function test_visitante_e_redirecionado_ao_login(): void {
        $response = $this->get(route('admin.contaAngra.linhasDoTempo.index'));
        $response->assertRedirect(route('admin.login'));
    }

    public function test_usuario_com_permissao_acessa_index(): void {
        $user = $this->seedUserWithLinhasPermissao();
        if ($user === null) {
            $this->markTestSkipped('Sem estrutura no banco de testes.');
        }

        $response = $this->actingAs($user)->get(route('admin.contaAngra.linhasDoTempo.index'));
        $response->assertOk();
        $response->assertSeeText(__('Linhas do Tempo'), false);
    }

    public function test_criar_linha_do_tempo_e_ponto_historico(): void {
        $user = $this->seedUserWithLinhasPermissao();
        if ($user === null) {
            $this->markTestSkipped('Sem estrutura no banco de testes.');
        }

        $this->actingAs($user);

        $response = $this->post(route('admin.contaAngra.linhasDoTempo.store'), [
            'name' => 'Contrato teste LT',
            'event_date' => '2024-01-15',
            'process_text' => '<p>Processo inicial</p>',
            'description' => 'Resumo',
            'tags_input' => 'tag1, tag2',
        ]);
        $response->assertRedirect();
        $timeline = Timeline::query()->where('user_id', $user->id)->orderByDesc('created_at')->first();
        $this->assertNotNull($timeline);

        $responsePoint = $this->postJson(route('admin.contaAngra.linhasDoTempo.pontos.store', $timeline), [
            'name' => 'Vistoria',
            'event_date' => '2024-02-01 10:00:00',
            'process_text' => '<p>Primeira vistoria</p>',
        ]);
        $responsePoint->assertOk();
        $this->assertDatabaseHas('lt_historical_points', [
            'timeline_id' => $timeline->id,
            'name' => 'Vistoria',
        ]);
    }

    public function test_rn09_impede_ponto_duplicado_mesmo_nome_e_data(): void {
        $user = $this->seedUserWithLinhasPermissao();
        if ($user === null) {
            $this->markTestSkipped('Sem estrutura no banco de testes.');
        }

        $timeline = Timeline::query()->create([
            'user_id' => $user->id,
            'name' => 'TL dup',
            'process_text' => '<p>x</p>',
            'event_date' => '2024-03-01',
            'tags' => [],
            'status' => 'active',
        ]);

        $this->actingAs($user)->postJson(route('admin.contaAngra.linhasDoTempo.pontos.store', $timeline), [
            'name' => 'Evento X',
            'event_date' => '2024-04-01 08:00:00',
            'process_text' => '<p>a</p>',
        ])->assertOk();

        $responseDup = $this->actingAs($user)->postJson(route('admin.contaAngra.linhasDoTempo.pontos.store', $timeline), [
            'name' => 'Evento X',
            'event_date' => '2024-04-01 08:00:00',
            'process_text' => '<p>b</p>',
        ]);
        $responseDup->assertStatus(422);
    }

    public function test_rn04_nota_nao_editavel_apos_24h(): void {
        $user = $this->seedUserWithLinhasPermissao();
        if ($user === null) {
            $this->markTestSkipped('Sem estrutura no banco de testes.');
        }

        $timeline = Timeline::query()->create([
            'user_id' => $user->id,
            'name' => 'TL note',
            'process_text' => '<p>x</p>',
            'event_date' => '2024-05-01',
            'tags' => [],
            'status' => 'active',
        ]);

        $point = HistoricalPoint::query()->create([
            'timeline_id' => $timeline->id,
            'name' => 'P',
            'event_date' => '2024-05-02 10:00:00',
            'process_text' => '<p>p</p>',
            'status' => 'active',
        ]);

        $note = Note::query()->create([
            'historical_point_id' => $point->id,
            'author_id' => $user->id,
            'content' => 'Nota antiga',
            'status' => 'active',
        ]);
        \DB::table('lt_notes')->where('id', $note->id)->update([
            'created_at' => Carbon::now()->subDays(2),
            'updated_at' => Carbon::now()->subDays(2),
        ]);

        $this->actingAs($user);
        $response = $this->putJson(route('admin.contaAngra.linhasDoTempo.notas.update', [$timeline, $point, $note]), [
            'content' => 'Tentativa',
        ]);
        $response->assertStatus(422);
    }

}
