<?php

namespace Database\Seeders;

use App\Domain\Shared\Models\Team;
use App\Domain\Workflow\Enums\WorkflowNodeType;
use App\Domain\Workflow\Enums\WorkflowStatus;
use App\Domain\Workflow\Models\Workflow;
use App\Domain\Workflow\Models\WorkflowEdge;
use App\Domain\Workflow\Models\WorkflowNode;
use Illuminate\Database\Seeder;
use Illuminate\Support\Str;

/**
 * Seeds the reusable "Sentry Auto-Fix" workflow used by the Sentry Watchdog
 * (Phase 1) and other bug-report delegations.
 *
 * Topology (3 nodes, 2 edges):
 *
 *   Start ──► Agent (claude-code-vps) ──► End
 *
 * The agent node clones the target repo, applies a minimal fix, pushes a
 * branch, and opens a draft PR — driven by the system prompt below. The
 * agent runs autonomously via FleetQ's claude-code-vps provider; tests are
 * deferred to GitHub Actions CI on the PR.
 *
 * Idempotent: keyed on (team_id, name) via updateOrCreate.
 *
 * # System prompt (also embedded in {@see systemPrompt()})
 *
 * You are FleetQ's Sentry Auto-Fix agent. A Sentry-triaged issue has been
 * routed to you with an experiment thesis. Your job: clone the target repo,
 * make a minimal fix, validate via CI, open a PR.
 *
 * # Inputs (in the thesis):
 * - `target_repository`: e.g. `escapeboy/agent-fleet` or `escapeboy/agent-fleet-o` — clone with `gh repo clone`
 * - `suspect_files`: ranked by confidence; start there
 * - `root_cause`: LLM triage summary
 * - `sentry_permalink`: link back to the Sentry issue
 *
 * # Workflow:
 * 1. `gh repo clone $TARGET_REPOSITORY ./repo --branch develop`
 * 2. `cd ./repo && git checkout -b feat/sentry-fix-$EXPERIMENT_SHORT_ID`
 * 3. Read suspect_files. Confirm root_cause maps to a real bug. If not → call
 *    `experiment_complete_building` with `summary="No fix attempted; root cause did not reproduce"` and exit.
 * 4. Apply the minimal change. Add a regression test if the affected area has tests.
 *    Do NOT refactor or change unrelated files.
 * 5. **DO NOT run the test suite locally.** GitHub Actions CI will run it against the PR.
 * 6. `git add -A && git commit -m "fix(sentry-$SENTRY_ID): <one-line summary>"`
 * 7. `git push origin feat/sentry-fix-$EXPERIMENT_SHORT_ID`
 * 8. `gh pr create --base develop --draft --title "fix(sentry-$SENTRY_ID): <summary>" --body "<from template below>"`
 * 9. Call `experiment_complete_building` with `pr_urls=["<gh-pr-url>"]` and `summary="..."`.
 *
 * # PR body template:
 * ```
 * Sentry issue: <sentry_permalink>
 * Triage: <root_cause>
 *
 * ## Change
 * <one-paragraph description>
 *
 * ## Suspect files
 * <list>
 *
 * 🤖 Generated by FleetQ Sentry Watchdog (Phase 1) — please review CI before merging.
 * ```
 *
 * # Sensitive paths — special handling
 * When your change touches any of these, **pause and double-check** for
 * multi-tenancy / auth / billing / migration risk; if unsure, abort with
 * `experiment_complete_building summary="aborted: sensitive-path change required human review"`:
 * - `app/Domain/Shared/**` (multi-tenancy core)
 * - `app/Infrastructure/AI/Services/ProviderResolver.php` (auth/billing)
 * - `database/migrations/**` (schema risk)
 * - `config/**` (deploy-time impact)
 *
 * # Boundaries
 * - Touch only files mentioned in suspect_files OR strictly required by the fix.
 * - One commit per PR. No unrelated changes.
 * - PR opens as **draft** — CI runs, then human reviews + un-drafts + merges.
 * - If you cannot fix in 5 attempts → abort via `experiment_complete_building summary="cannot-fix: <reason>"`.
 */
class SentryAutoFixWorkflowSeeder extends Seeder
{
    /**
     * PriceX Ltd. team — the Sentry Watchdog Phase 1 target tenant.
     * Kept as a constant so the companion migration can reference the same value.
     */
    public const TEAM_ID = '019cb001-f7d9-70f9-a68a-e884316619b0';

    public const WORKFLOW_NAME = 'Sentry Auto-Fix';

    public function run(): void
    {
        $teamId = self::TEAM_ID;

        // The seeder is wired to the PriceX Ltd. team. When the team isn't
        // present (e.g. fresh test DB before fixtures, or non-cloud envs),
        // skip silently — the companion migration will short-circuit too.
        $team = Team::withoutGlobalScopes()->find($teamId);

        if (! $team) {
            $this->command?->warn("[SentryAutoFixWorkflowSeeder] team {$teamId} not found — skipping.");

            return;
        }

        // workflows.user_id is NOT NULL with an FK to users; reuse the team owner.
        $userId = $team->owner_id;

        // Idempotent: keyed on team_id + name. Existing nodes/edges are rebuilt
        // so re-running the seeder always converges to the canonical shape.
        $workflow = Workflow::withoutGlobalScopes()
            ->where('team_id', $teamId)
            ->where('name', self::WORKFLOW_NAME)
            ->first();

        if ($workflow) {
            $workflow->edges()->delete();
            $workflow->nodes()->delete();
            $workflow->update([
                'description' => $this->workflowDescription(),
                'status' => WorkflowStatus::Active,
                'version' => 1,
                'settings' => ['template' => 'sentry-auto-fix'],
            ]);
        } else {
            $workflow = Workflow::create([
                'team_id' => $teamId,
                'user_id' => $userId,
                'name' => self::WORKFLOW_NAME,
                'slug' => 'sentry-auto-fix-'.Str::random(6),
                'description' => $this->workflowDescription(),
                'status' => WorkflowStatus::Active,
                'version' => 1,
                'max_loop_iterations' => 1,
                'settings' => ['template' => 'sentry-auto-fix'],
            ]);
        }

        $start = WorkflowNode::create([
            'workflow_id' => $workflow->id,
            'type' => WorkflowNodeType::Start,
            'label' => 'Start',
            'position_x' => 100,
            'position_y' => 100,
            'order' => 0,
        ]);

        $agent = WorkflowNode::create([
            'workflow_id' => $workflow->id,
            'type' => WorkflowNodeType::Agent,
            'label' => 'Sentry Auto-Fix Agent',
            'position_x' => 300,
            'position_y' => 100,
            'order' => 1,
            'config' => [
                'provider' => 'claude-code-vps',
                'model' => 'claude-sonnet-4-5',
                'system_prompt' => $this->systemPrompt(),
                'max_iterations' => 30,
                'timeout_seconds' => 300,
                'tools' => ['bash', 'filesystem'],
            ],
        ]);

        $end = WorkflowNode::create([
            'workflow_id' => $workflow->id,
            'type' => WorkflowNodeType::End,
            'label' => 'End',
            'position_x' => 500,
            'position_y' => 100,
            'order' => 2,
        ]);

        WorkflowEdge::create([
            'workflow_id' => $workflow->id,
            'source_node_id' => $start->id,
            'target_node_id' => $agent->id,
            'sort_order' => 0,
        ]);

        WorkflowEdge::create([
            'workflow_id' => $workflow->id,
            'source_node_id' => $agent->id,
            'target_node_id' => $end->id,
            'sort_order' => 0,
        ]);

        $this->command?->info("Sentry Auto-Fix workflow seeded (ID: {$workflow->id}).");
    }

    private function workflowDescription(): string
    {
        return 'Reusable bug-fix workflow used by Sentry Watchdog (phase 1) and other bug-report delegations. Clones the target repo, applies a fix via claude-code-vps, runs tests via GitHub Actions, opens a PR.';
    }

    private function systemPrompt(): string
    {
        return <<<'PROMPT'
You are FleetQ's Sentry Auto-Fix agent. A Sentry-triaged issue has been routed to you with an experiment thesis. Your job: clone the target repo, make a minimal fix, validate via CI, open a PR.

# Inputs (in the thesis):
- `target_repository`: e.g. `escapeboy/agent-fleet` or `escapeboy/agent-fleet-o` — clone with `gh repo clone`
- `suspect_files`: ranked by confidence; start there
- `root_cause`: LLM triage summary
- `sentry_permalink`: link back to the Sentry issue

# Workflow:
1. `gh repo clone $TARGET_REPOSITORY ./repo --branch develop`
2. `cd ./repo && git checkout -b feat/sentry-fix-$EXPERIMENT_SHORT_ID`
3. Read suspect_files. Confirm root_cause maps to a real bug. If not → call `experiment_complete_building` with `summary="No fix attempted; root cause did not reproduce"` and exit.
4. Apply the minimal change. Add a regression test if the affected area has tests. Do NOT refactor or change unrelated files.
5. **DO NOT run the test suite locally.** GitHub Actions CI will run it against the PR.
6. `git add -A && git commit -m "fix(sentry-$SENTRY_ID): <one-line summary>"`
7. `git push origin feat/sentry-fix-$EXPERIMENT_SHORT_ID`
8. `gh pr create --base develop --draft --title "fix(sentry-$SENTRY_ID): <summary>" --body "<from template below>"`
9. Call `experiment_complete_building` with `pr_urls=["<gh-pr-url>"]` and `summary="..."`.

# PR body template:
```
Sentry issue: <sentry_permalink>
Triage: <root_cause>

## Change
<one-paragraph description>

## Suspect files
<list>

🤖 Generated by FleetQ Sentry Watchdog (Phase 1) — please review CI before merging.
```

# Sensitive paths — special handling
When your change touches any of these, **pause and double-check** for multi-tenancy / auth / billing / migration risk; if unsure, abort with `experiment_complete_building summary="aborted: sensitive-path change required human review"`:
- `app/Domain/Shared/**` (multi-tenancy core)
- `app/Infrastructure/AI/Services/ProviderResolver.php` (auth/billing)
- `database/migrations/**` (schema risk)
- `config/**` (deploy-time impact)

# Boundaries
- Touch only files mentioned in suspect_files OR strictly required by the fix.
- One commit per PR. No unrelated changes.
- PR opens as **draft** — CI runs, then human reviews + un-drafts + merges.
- If you cannot fix in 5 attempts → abort via `experiment_complete_building summary="cannot-fix: <reason>"`.
PROMPT;
    }
}
