Feature: Project CLI command functions coverage
  As a developer
  I want the project CLI command functions exercised directly
  So that cli/commands/project.py achieves high coverage

  Background:
    Given a project CLI commands test database is initialized

  # ── helpers that are never reached from the repository-only tests ──

  Scenario: _get_namespaced_project_repo returns a repository
    When I call _get_namespaced_project_repo via the patched container
    Then the helper should return a NamespacedProjectRepository

  Scenario: _get_resource_link_repo returns a repository
    When I call _get_resource_link_repo via the patched container
    Then the helper should return a ProjectResourceLinkRepository

  Scenario: _get_resource_registry_service returns a service
    When I call _get_resource_registry_service via the patched container
    Then the helper should return a ResourceRegistryService

  Scenario: _store_project_extras stores invariants via file DB
    When I call _store_project_extras with invariants "no-delete" and actor "guard"
    Then the extras call should complete without error

  # ── create command ────────────────────────────────────────────

  Scenario: create command with bare name uses rich output
    When I invoke project-create with bare name "my-app"
    Then the project cmd output should contain "created"
    And the project cmd should succeed

  Scenario: create command with explicit namespace
    When I invoke project-create with bare name "team/my-svc"
    Then the project cmd output should contain "created"
    And the project cmd should succeed

  Scenario: create command with description
    When I invoke project-create with name "desc-proj" description "A nice project"
    Then the project cmd output should contain "created"
    And the project cmd should succeed

  Scenario: create command with json format
    When I invoke project-create with name "json-proj" format "json"
    Then the project cmd output should contain "namespaced_name"
    And the project cmd should succeed

  Scenario: create command with invariants
    When I invoke project-create with name "inv-proj" invariant "do not delete files"
    Then the project cmd output should contain "created"
    And the project cmd should succeed

  Scenario: create command with linked resource
    Given a resource "my-git-res" is registered in the commands DB
    When I invoke project-create with name "res-proj" linking resource "my-git-res"
    Then the project cmd output should contain "created"
    And the project cmd should succeed

  Scenario: create command with invalid name fails
    When I invoke project-create with bare name "123bad"
    Then the project cmd should fail

  Scenario: create command with DatabaseError from repo
    When I invoke project-create triggering a database error
    Then the project cmd should fail

  # ── list command ─────────────────────────────────────────────

  Scenario: list command shows projects in rich format
    Given a project "local/list-a" is created in the commands DB
    And a project "local/list-b" is created in the commands DB
    When I invoke project-list with default options
    Then the project cmd output should contain "list-a"
    And the project cmd output should contain "list-b"

  Scenario: list command with namespace filter
    Given a project "local/ns-x" is created in the commands DB
    And a project "team/ns-y" is created in the commands DB
    When I invoke project-list with namespace "team"
    Then the project cmd output should contain "ns-y"

  Scenario: list command with regex filter
    Given a project "local/api-svc" is created in the commands DB
    And a project "local/web-ui" is created in the commands DB
    When I invoke project-list with regex "api"
    Then the project cmd output should contain "api-svc"

  Scenario: list command with invalid regex fails
    When I invoke project-list with invalid regex "[bad"
    Then the project cmd should fail

  Scenario: list command when empty
    When I invoke project-list with default options
    Then the project cmd output should contain "No projects found"

  Scenario: list command with json format
    Given a project "local/fmt-list" is created in the commands DB
    When I invoke project-list with format "json"
    Then the project cmd output should contain "namespaced_name"

  # ── show command ─────────────────────────────────────────────

  Scenario: show command displays project in rich format
    Given a project "local/show-cmd" is created in the commands DB
    When I invoke project-show for "local/show-cmd" default format
    Then the project cmd output should contain "show-cmd"
    And the project cmd should succeed

  Scenario: show command with linked resources
    Given a project "local/show-linked" is created in the commands DB
    And a resource is linked to project "local/show-linked" in the commands DB
    When I invoke project-show for "local/show-linked" default format
    Then the project cmd output should contain "show-linked"

  Scenario: show command with json format
    Given a project "local/show-json" is created in the commands DB
    When I invoke project-show for "local/show-json" format "json"
    Then the project cmd output should contain "namespaced_name"

  Scenario: show nonexistent project fails
    When I invoke project-show for "local/ghost" default format
    Then the project cmd should fail

  # ── link-resource command ────────────────────────────────────

  Scenario: link-resource command in rich format
    Given a project "local/link-cmd" is created in the commands DB
    And a resource "link-res" is registered in the commands DB
    When I invoke project-link for "local/link-cmd" resource "link-res" default format
    Then the project cmd output should contain "Linked"
    And the project cmd should succeed

  Scenario: link-resource command with read-only
    Given a project "local/ro-cmd" is created in the commands DB
    And a resource "ro-res" is registered in the commands DB
    When I invoke project-link for "local/ro-cmd" resource "ro-res" read-only
    Then the project cmd output should contain "read-only"
    And the project cmd should succeed

  Scenario: link-resource command with json format
    Given a project "local/link-json" is created in the commands DB
    And a resource "json-res" is registered in the commands DB
    When I invoke project-link for "local/link-json" resource "json-res" format "json"
    Then the project cmd output should contain "resource_id"

  Scenario: link-resource to nonexistent project fails
    When I invoke project-link for "local/nope" resource "anything" default format
    Then the project cmd should fail

  Scenario: link-resource with nonexistent resource fails
    Given a project "local/link-fail" is created in the commands DB
    When I invoke project-link for "local/link-fail" resource "no-such-res" default format
    Then the project cmd should fail

  # ── unlink-resource command ──────────────────────────────────

  Scenario: unlink-resource command in rich format
    Given a project "local/unlink-cmd" is created in the commands DB
    And a resource is linked to project "local/unlink-cmd" in the commands DB
    When I invoke project-unlink for "local/unlink-cmd" with yes default format
    Then the project cmd output should contain "Unlinked"
    And the project cmd should succeed

  Scenario: unlink-resource command with json format
    Given a project "local/unlink-json" is created in the commands DB
    And a resource is linked to project "local/unlink-json" in the commands DB
    When I invoke project-unlink for "local/unlink-json" with yes format "json"
    Then the project cmd output should contain "unlinked"

  Scenario: unlink-resource for nonexistent project fails
    When I invoke project-unlink for "local/ghost-proj" resource "any" with yes
    Then the project cmd should fail

  Scenario: unlink-resource for nonexistent resource fails
    Given a project "local/unlink-fail" is created in the commands DB
    When I invoke project-unlink for "local/unlink-fail" resource "no-such" with yes
    Then the project cmd should fail

  Scenario: unlink-resource when resource not linked fails
    Given a project "local/unlink-none" is created in the commands DB
    And a resource "orphan-res" is registered in the commands DB
    When I invoke project-unlink for "local/unlink-none" resource "orphan-res" with yes
    Then the project cmd should fail

  # ── delete command ───────────────────────────────────────────

  Scenario: delete command removes project
    Given a project "local/del-cmd" is created in the commands DB
    When I invoke project-delete for "local/del-cmd" with yes
    Then the project cmd output should contain "deleted"
    And the project cmd should succeed

  Scenario: delete command with json format
    Given a project "local/del-json" is created in the commands DB
    When I invoke project-delete for "local/del-json" with yes format "json"
    Then the project cmd output should contain "deleted"

  Scenario: delete command JSON includes deletion timestamp
    Given a project "local/del-json-ts" is created in the commands DB
    When I invoke project-delete for "local/del-json-ts" with yes format "json"
    Then the project cmd JSON data should include deleted_at

  Scenario: delete nonexistent project fails
    When I invoke project-delete for "local/nope" with yes
    Then the project cmd should fail

  Scenario: delete project with linked resources without force fails
    Given a project "local/del-linked" is created in the commands DB
    And a resource is linked to project "local/del-linked" in the commands DB
    When I invoke project-delete for "local/del-linked" with yes no force
    Then the project cmd should fail

  Scenario: delete project with linked resources with force succeeds
    Given a project "local/del-force" is created in the commands DB
    And a resource is linked to project "local/del-force" in the commands DB
    When I invoke project-delete for "local/del-force" with yes and force
    Then the project cmd output should contain "deleted"
    And the project cmd should succeed

  Scenario: delete command accepts -f short form for --force
    Given a project "local/del-sf" is created in the commands DB
    And a resource is linked to project "local/del-sf" in the commands DB
    When I invoke project-delete for "local/del-sf" with yes and short force flag
    Then the project cmd output should contain "deleted"
    And the project cmd should succeed
