# Repository indexing service tests targeting issue #195.
@feature195
Feature: Repository indexing with incremental refresh and language detection
  As a CleverAgents user with a large project
  I want the system to index my repository files with language detection
  So that context assembly can efficiently retrieve relevant code fragments

  # -- Full index ----------------------------------------------------------

  @feature195
  Scenario: Full index of a repository with mixed file types
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files
    When I run repo-index full index on the sample directory
    Then the repo-index result status should be "ready"
    And the repo-index result file count should be 6
    And the repo-index primary language should be "python"
    And the repo-index token estimate should be positive

  @feature195
  Scenario: Indexed files have correct language detection
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files
    When I run repo-index full index on the sample directory
    Then the repo-index file "main.py" should have language "python"
    And the repo-index file "index.ts" should have language "typescript"
    And the repo-index file "README.md" should have language "markdown"
    And the repo-index file "config.json" should have language "json"
    And the repo-index file "Makefile" should have language "makefile"

  @feature195
  Scenario: Index is persisted and can be retrieved
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files
    When I run repo-index full index on the sample directory
    And I query repo-index for the indexed resource
    Then the repo-index retrieved index should match the original
    And the repo-index retrieved file hashes should match the original

  # -- Incremental refresh -------------------------------------------------

  @feature195
  Scenario: Incremental refresh detects changed files
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files
    And I run repo-index full index on the sample directory
    When I modify repo-index file "main.py" with new content
    And I run repo-index incremental refresh
    Then the repo-index file "main.py" content hash should differ from original
    And the repo-index file "index.ts" content hash should match original

  @feature195
  Scenario: Refresh on non-existent index falls back to full index
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files
    When I run repo-index incremental refresh
    Then the repo-index result status should be "ready"
    And the repo-index result file count should be 6

  # -- Policy enforcement --------------------------------------------------

  @feature195
  Scenario: Max file size excludes large files
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files and a 2MB file
    When I run repo-index full index with max file size 1000000 bytes
    Then the repo-index result should not include file "big_file.dat"
    And the repo-index result file count should be 6

  @feature195
  Scenario: Include globs filter to matching files only
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files
    When I run repo-index full index with include globs "*.py"
    Then the repo-index result file count should be 2
    And the repo-index primary language should be "python"

  @feature195
  Scenario: Exclude globs remove matching files
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files
    When I run repo-index full index with exclude globs "*.md,*.json"
    Then the repo-index result should not include file "README.md"
    And the repo-index result should not include file "config.json"

  @feature195
  Scenario: Max total size truncates indexing
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files and a 2MB file
    When I run repo-index full index with max total size 100 bytes
    Then the repo-index result file count should be less than 6

  @feature195
  Scenario: Indexing 10,000 files completes within timeout bound
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with 10000 python files
    When I run repo-index full index with timeout of 120 seconds
    Then the repo-index result status should be "ready"
    And the repo-index result file count should be 10000
    And the repo-index indexing elapsed seconds should be less than 120

  # -- Removal -------------------------------------------------------------

  @feature195
  Scenario: Remove index cleans up all records
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files
    And I run repo-index full index on the sample directory
    When I remove the repo-index for the resource
    Then querying repo-index for the resource should return nothing

  @feature195
  Scenario: Remove non-existent index returns false
    Given a repo-index fresh in-memory indexing service
    When I remove the repo-index for a non-existent resource
    Then the repo-index removal result should be false

  # -- Error handling ------------------------------------------------------

  @feature195
  Scenario: Index with empty resource ID raises error
    Given a repo-index fresh in-memory indexing service
    When I attempt repo-index with empty resource ID
    Then a repo-index ValueError should be raised mentioning "non-empty"

  @feature195
  Scenario: Index with non-existent path raises error
    Given a repo-index fresh in-memory indexing service
    When I attempt repo-index with non-existent path "/nonexistent/xyz"
    Then a repo-index FileNotFoundError should be raised

  @feature195
  Scenario: Index with invalid ULID resource ID raises error
    Given a repo-index fresh in-memory indexing service
    When I attempt repo-index with invalid ULID resource ID
    Then a repo-index ValueError should be raised mentioning "valid ULID"

  # -- Status query ---------------------------------------------------------

  @feature195
  Scenario: Get index status returns metadata without file records
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files
    And I run repo-index full index on the sample directory
    When I query repo-index status for the indexed resource
    Then the repo-index status metadata should have status "ready"
    And the repo-index status metadata file count should be 6

  # -- Additional edge cases -----------------------------------------------

  @feature195
  Scenario: Index with file path as root raises error
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files
    When I attempt repo-index with a file path as root
    Then a repo-index ValueError should be raised mentioning "not a directory"

  @feature195
  Scenario: Index on empty directory returns zero files with ready status
    Given a repo-index fresh in-memory indexing service
    And a repo-index empty temporary directory
    When I run repo-index full index on the sample directory
    Then the repo-index result status should be "ready"
    And the repo-index result file count should be 0
    And the repo-index primary language should be "unknown"

  # -- Refresh error paths -------------------------------------------------

  @feature195
  Scenario: Refresh with non-existent path raises error
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files
    And I run repo-index full index on the sample directory
    When I attempt repo-index refresh with non-existent path "/nonexistent/xyz"
    Then a repo-index FileNotFoundError should be raised

  @feature195
  Scenario: Refresh with file path as root raises error
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files
    And I run repo-index full index on the sample directory
    When I attempt repo-index refresh with a file path as root
    Then a repo-index ValueError should be raised mentioning "not a directory"

  # -- Fault tolerance paths -----------------------------------------------

  @feature195
  Scenario: Walk failure on fresh resource persists ERROR status
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files
    When repo-index walk is mocked to fail and I index a fresh resource
    Then a repo-index error should be raised
    And querying repo-index status for the resource should show "error"

  @feature195
  Scenario: Walk failure on existing resource preserves previous index
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files
    And I run repo-index full index on the sample directory
    When repo-index walk is mocked to fail and I re-index
    Then a repo-index error should be raised
    And the repo-index previous index should still be retrievable with 6 files

  @feature195
  Scenario: Refresh walk failure preserves previous good index
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files
    And I run repo-index full index on the sample directory
    When repo-index walk is mocked to fail and I refresh
    Then a repo-index error should be raised
    And the repo-index previous index should still be retrievable with 6 files

  # -- Stale indexing cleanup ------------------------------------------------

  @feature195
  Scenario: Cleanup stale indexing removes orphan INDEXING rows
    Given a repo-index fresh in-memory indexing service
    And a repo-index stale INDEXING row is inserted for a resource
    When I call repo-index cleanup stale indexing
    Then the repo-index cleanup should report 1 stale row removed
    And querying repo-index for the stale resource should return nothing

  # -- Edge cases: unreadable files, naive datetimes -----------------------

  @feature195
  Scenario: Unreadable file is skipped without crashing index
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with a file that fails hashing
    When I run repo-index full index with hash failure on "secret.dat"
    Then the repo-index result status should be "ready"
    And the repo-index result should not include file "secret.dat"

  @feature195
  Scenario: Re-index replaces existing index completely
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files
    And I run repo-index full index on the sample directory
    When I add a new file "extra.py" and re-index
    Then the repo-index result file count should be 7
    And the repo-index result status should be "ready"

  @feature195
  Scenario: Naive datetime is coerced to UTC in FileRecord
    Given a repo-index fresh in-memory indexing service
    When I create a FileRecord with a naive datetime
    Then the FileRecord last_modified should have UTC timezone

  @feature195
  Scenario: Naive datetime is coerced to UTC in IndexMetadata
    Given a repo-index fresh in-memory indexing service
    When I create an IndexMetadata with a naive datetime
    Then the IndexMetadata indexed_at should have UTC timezone

  # -- Domain model structural assertions ----------------------------------

  @feature195
  Scenario: IndexMetadata has all spec-required fields
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files
    When I run repo-index full index on the sample directory
    Then the repo-index metadata should have field "index_id"
    And the repo-index metadata should have field "resource_id"
    And the repo-index metadata should have field "indexed_at"
    And the repo-index metadata should have field "file_count"
    And the repo-index metadata should have field "token_estimate"
    And the repo-index metadata should have field "primary_language"
    And the repo-index metadata should have field "status"

  @feature195
  Scenario: FileRecord has all spec-required fields
    Given a repo-index fresh in-memory indexing service
    And a repo-index temporary directory with sample project files
    When I run repo-index full index on the sample directory
    Then each repo-index file record should have field "path"
    And each repo-index file record should have field "content_hash"
    And each repo-index file record should have field "token_count"
    And each repo-index file record should have field "language"
    And each repo-index file record should have field "size_bytes"
    And each repo-index file record should have field "last_modified"
