<?php

namespace Drupal\Tests\eb\Kernel\Entity;

use Drupal\eb\Entity\EbRollback;
use Drupal\Tests\eb\Kernel\EbKernelTestBase;

/**
 * Kernel tests for EbRollback content entity.
 *
 * @coversDefaultClass \Drupal\eb\Entity\EbRollback
 * @group eb
 */
class EbRollbackEntityTest extends EbKernelTestBase {

  /**
   * Tests creating a rollback entity with required fields.
   *
   * @covers ::baseFieldDefinitions
   * @covers ::label
   */
  public function testCreateRollbackEntity(): void {
    $rollback = EbRollback::create([
      'label' => 'Test Rollback',
    ]);
    $rollback->save();

    $loaded = EbRollback::load($rollback->id());
    $this->assertNotNull($loaded);
    $this->assertEquals('Test Rollback', $loaded->label());
    $this->assertNotNull($loaded->uuid());
    $this->assertGreaterThan(0, $loaded->id());
  }

  /**
   * Tests default status is 'pending'.
   *
   * @covers ::getStatus
   */
  public function testDefaultStatusIsPending(): void {
    $rollback = EbRollback::create([
      'label' => 'Pending Rollback',
    ]);
    $rollback->save();

    $this->assertEquals('pending', $rollback->getStatus());
    $this->assertTrue($rollback->isPending());
    $this->assertFalse($rollback->isCompleted());
  }

  /**
   * Tests status transitions.
   *
   * @covers ::setStatus
   * @covers ::getStatus
   * @covers ::isPending
   * @covers ::isCompleted
   */
  public function testStatusTransitions(): void {
    $rollback = EbRollback::create([
      'label' => 'Status Test',
    ]);
    $rollback->save();

    // Initial state.
    $this->assertTrue($rollback->isPending());
    $this->assertFalse($rollback->isCompleted());

    // Transition to completed.
    $rollback->setStatus('completed');
    $rollback->save();

    $loaded = EbRollback::load($rollback->id());
    $this->assertEquals('completed', $loaded->getStatus());
    $this->assertFalse($loaded->isPending());
    $this->assertTrue($loaded->isCompleted());

    // Transition to failed.
    $loaded->setStatus('failed');
    $loaded->save();

    $reloaded = EbRollback::load($loaded->id());
    $this->assertEquals('failed', $reloaded->getStatus());
    $this->assertFalse($reloaded->isPending());
    $this->assertFalse($reloaded->isCompleted());
  }

  /**
   * Tests definition_id field.
   *
   * @covers ::getDefinitionId
   * @covers ::setDefinitionId
   */
  public function testDefinitionIdField(): void {
    $rollback = EbRollback::create([
      'label' => 'Definition Test',
    ]);
    $rollback->save();

    // Default is NULL.
    $this->assertNull($rollback->getDefinitionId());

    // Set and verify.
    $rollback->setDefinitionId('my_definition');
    $rollback->save();

    $loaded = EbRollback::load($rollback->id());
    $this->assertEquals('my_definition', $loaded->getDefinitionId());
  }

  /**
   * Tests operation_count field.
   *
   * @covers ::getOperationCount
   * @covers ::setOperationCount
   */
  public function testOperationCountField(): void {
    $rollback = EbRollback::create([
      'label' => 'Count Test',
    ]);
    $rollback->save();

    // Default is 0.
    $this->assertEquals(0, $rollback->getOperationCount());

    // Set and verify.
    $rollback->setOperationCount(5);
    $rollback->save();

    $loaded = EbRollback::load($rollback->id());
    $this->assertEquals(5, $loaded->getOperationCount());
  }

  /**
   * Tests completed timestamp.
   *
   * @covers ::getCompletedTime
   * @covers ::setCompletedTime
   */
  public function testCompletedTimestamp(): void {
    $rollback = EbRollback::create([
      'label' => 'Timestamp Test',
    ]);
    $rollback->save();

    // Default is NULL.
    $this->assertNull($rollback->getCompletedTime());

    // Set and verify.
    $timestamp = time();
    $rollback->setCompletedTime($timestamp);
    $rollback->save();

    $loaded = EbRollback::load($rollback->id());
    $this->assertEquals($timestamp, $loaded->getCompletedTime());
  }

  /**
   * Tests EntityOwnerTrait integration.
   *
   * @covers ::getOwner
   * @covers ::getOwnerId
   * @covers ::setOwnerId
   */
  public function testEntityOwnerTrait(): void {
    $rollback = EbRollback::create([
      'label' => 'Owner Test',
    ]);
    $rollback->save();

    // Owner should be current user (admin).
    $this->assertEquals($this->adminUser->id(), $rollback->getOwnerId());
    $this->assertEquals($this->adminUser->id(), $rollback->getOwner()->id());
  }

  /**
   * Tests EntityChangedTrait integration.
   *
   * @covers ::getChangedTime
   */
  public function testEntityChangedTrait(): void {
    $rollback = EbRollback::create([
      'label' => 'Changed Test',
    ]);
    $rollback->save();

    // Created time should be recent (within last minute).
    $created = (int) $rollback->get('created')->value;
    $this->assertGreaterThan(time() - 60, $created);
    $this->assertLessThanOrEqual(time(), $created);

    // Changed time should be set.
    $this->assertGreaterThan(0, $rollback->getChangedTime());
  }

  /**
   * Tests isPending() and isCompleted() helper methods.
   *
   * @covers ::isPending
   * @covers ::isCompleted
   */
  public function testStatusHelperMethods(): void {
    $rollback = EbRollback::create([
      'label' => 'Helper Test',
      'status' => 'pending',
    ]);
    $rollback->save();

    $this->assertTrue($rollback->isPending());
    $this->assertFalse($rollback->isCompleted());

    $rollback->setStatus('completed')->save();
    $this->assertFalse($rollback->isPending());
    $this->assertTrue($rollback->isCompleted());

    $rollback->setStatus('failed')->save();
    $this->assertFalse($rollback->isPending());
    $this->assertFalse($rollback->isCompleted());
  }

  /**
   * Tests rollback entity deletion.
   */
  public function testDeleteRollback(): void {
    $rollback = EbRollback::create([
      'label' => 'Delete Test',
    ]);
    $rollback->save();
    $id = $rollback->id();

    $this->assertNotNull(EbRollback::load($id));

    $rollback->delete();
    $this->assertNull(EbRollback::load($id));
  }

  /**
   * Tests fluent interface for setters.
   *
   * @covers ::setDefinitionId
   * @covers ::setStatus
   * @covers ::setOperationCount
   * @covers ::setCompletedTime
   */
  public function testFluentInterface(): void {
    $rollback = EbRollback::create([
      'label' => 'Fluent Test',
    ]);

    $result = $rollback
      ->setDefinitionId('fluent_def')
      ->setStatus('completed')
      ->setOperationCount(10)
      ->setCompletedTime(12345678);

    $this->assertSame($rollback, $result);
    $this->assertEquals('fluent_def', $rollback->getDefinitionId());
    $this->assertEquals('completed', $rollback->getStatus());
    $this->assertEquals(10, $rollback->getOperationCount());
    $this->assertEquals(12345678, $rollback->getCompletedTime());
  }

}
