<?php

namespace App\Livewire\Tools;

use App\Domain\Credential\Enums\CredentialStatus;
use App\Domain\Credential\Enums\CredentialType;
use App\Domain\Credential\Models\Credential;
use App\Domain\Tool\Actions\CreateToolAction;
use App\Domain\Tool\Enums\BuiltInToolKind;
use App\Domain\Tool\Enums\ToolRiskLevel;
use App\Domain\Tool\Enums\ToolType;
use Illuminate\Support\Facades\Gate;
use Livewire\Component;

class CreateToolForm extends Component
{
    public int $step = 1;

    // Step 1: Basics
    public string $name = '';

    public string $description = '';

    public string $type = 'mcp_stdio';

    // Step 2: Transport Configuration
    // MCP stdio
    public string $mcpCommand = '';

    public string $mcpArgs = '';

    public string $mcpEnv = '';

    // MCP HTTP
    public string $mcpUrl = '';

    // MCP Bridge
    public string $bridgeServerName = '';

    public string $mcpHeaders = '';

    // Built-in
    public string $builtInKind = 'bash';

    public string $allowedCommands = 'curl, jq, python3, node, grep, awk, sed, cat, echo, ls, find, wc, head, tail, sort, uniq';

    public string $allowedPaths = '/tmp/agent-workspace';

    public bool $readOnly = false;

    // SSH-specific
    public string $sshHost = '';

    public int $sshPort = 22;

    public string $sshUsername = 'root';

    public string $sshCredentialId = '';

    public string $sshAllowedCommands = '';

    // Credentials (optional)
    public string $credentialMode = 'inline'; // 'inline' | 'reference'

    public string $apiKey = '';

    public string $credentialId = '';

    public string $credentialEnvVar = 'API_KEY';

    // Tool definitions (MCP - JSON)
    public string $toolDefinitionsJson = '';

    // Risk Level
    public string $riskLevel = '';

    // Settings
    public int $timeout = 30;

    public function nextStep(): void
    {
        if ($this->step === 1) {
            $this->validate([
                'name' => 'required|min:2|max:255',
                'description' => 'max:1000',
                'type' => 'required|in:mcp_stdio,mcp_http,mcp_bridge,built_in,compute_endpoint',
            ]);
        }

        if ($this->step === 2) {
            $this->validateTransportConfig();
        }

        $this->step = min(3, $this->step + 1);
    }

    public function prevStep(): void
    {
        $this->step = max(1, $this->step - 1);
    }

    private function validateTransportConfig(): void
    {
        $type = ToolType::from($this->type);

        if ($type === ToolType::McpStdio) {
            $this->validate([
                'mcpCommand' => 'required|min:1',
            ]);
        }

        if ($type === ToolType::McpHttp) {
            $this->validate([
                'mcpUrl' => 'required|url',
            ]);
        }

        if ($type === ToolType::McpBridge) {
            $this->validate([
                'bridgeServerName' => 'required|string|min:1|max:100',
            ]);
        }

        if ($type === ToolType::BuiltIn && $this->builtInKind === 'ssh') {
            $this->validate([
                'sshHost' => 'required|string|max:255',
                'sshPort' => 'required|integer|min:1|max:65535',
                'sshUsername' => 'required|string|max:64',
                'sshCredentialId' => 'required|uuid',
            ]);
        }
    }

    public function save(): void
    {
        Gate::authorize('edit-content');

        $team = auth()->user()->currentTeam;
        $type = ToolType::from($this->type);

        $transportConfig = $this->buildTransportConfig($type);
        $credentials = $this->buildCredentials();
        $toolDefinitions = $this->parseToolDefinitions();
        $settings = array_filter(['timeout' => $this->timeout]);

        $tool = app(CreateToolAction::class)->execute(
            teamId: $team->id,
            name: $this->name,
            type: $type,
            description: $this->description ?: null,
            transportConfig: $transportConfig,
            credentials: $credentials ?: [],
            toolDefinitions: $toolDefinitions ?: [],
            settings: $settings,
            credentialId: $this->credentialMode === 'reference' && $this->credentialId ? $this->credentialId : null,
        );

        if ($this->riskLevel) {
            $tool->update(['risk_level' => ToolRiskLevel::from($this->riskLevel)]);
        }

        session()->flash('message', 'Tool created successfully!');

        $this->redirect(route('tools.index'));
    }

    private function buildTransportConfig(ToolType $type): array
    {
        return match ($type) {
            ToolType::McpStdio => array_filter([
                'command' => $this->mcpCommand,
                'args' => array_filter(array_map('trim', explode(',', $this->mcpArgs))),
                'env' => $this->parseKeyValuePairs($this->mcpEnv),
                'credential_env_var' => $this->credentialEnvVar ?: null,
            ], fn ($v) => $v !== null && $v !== [] && $v !== ''),
            ToolType::McpHttp => array_filter([
                'url' => $this->mcpUrl,
                'headers' => $this->parseKeyValuePairs($this->mcpHeaders),
                'credential_env_var' => $this->credentialEnvVar ?: null,
            ], fn ($v) => $v !== null && $v !== [] && $v !== ''),
            ToolType::McpBridge => [
                'bridge_server_name' => $this->bridgeServerName,
            ],
            ToolType::BuiltIn => $this->buildBuiltInConfig(),
            ToolType::ComputeEndpoint => [],
        };
    }

    private function buildBuiltInConfig(): array
    {
        if ($this->builtInKind === 'ssh') {
            return [
                'kind' => 'ssh',
                'host' => $this->sshHost,
                'port' => $this->sshPort,
                'username' => $this->sshUsername,
                'credential_id' => $this->sshCredentialId,
                'allowed_commands' => array_values(array_filter(array_map('trim', explode(',', $this->sshAllowedCommands)))),
            ];
        }

        if ($this->builtInKind === 'browser_relay') {
            return ['kind' => 'browser_relay'];
        }

        return [
            'kind' => $this->builtInKind,
            'allowed_commands' => array_filter(array_map('trim', explode(',', $this->allowedCommands))),
            'allowed_paths' => array_filter(array_map('trim', explode(',', $this->allowedPaths))),
            'read_only' => $this->readOnly,
        ];
    }

    private function buildCredentials(): array
    {
        // When using a referenced Credential, don't store an inline API key
        if ($this->credentialMode === 'reference') {
            return [];
        }

        return array_filter([
            'api_key' => $this->apiKey ?: null,
        ]);
    }

    private function parseToolDefinitions(): ?array
    {
        if (empty($this->toolDefinitionsJson)) {
            return null;
        }

        $decoded = json_decode($this->toolDefinitionsJson, true);

        return is_array($decoded) ? $decoded : null;
    }

    private function parseKeyValuePairs(string $input): array
    {
        if (empty(trim($input))) {
            return [];
        }

        $pairs = [];
        foreach (explode("\n", $input) as $line) {
            $line = trim($line);
            if (str_contains($line, '=')) {
                [$key, $value] = explode('=', $line, 2);
                $pairs[trim($key)] = trim($value);
            }
        }

        return $pairs;
    }

    public function render()
    {
        $types = ToolType::cases();

        // SSH credentials: only active SSH key credentials for the current team
        $sshCredentials = Credential::where('credential_type', CredentialType::SshKey)
            ->where('status', CredentialStatus::Active)
            ->orderBy('name')
            ->get(['id', 'name']);

        // Available credentials for linking (non-SSH, active)
        $availableCredentials = Credential::whereNotIn('credential_type', [CredentialType::SshKey->value])
            ->where('status', CredentialStatus::Active)
            ->orderBy('name')
            ->get(['id', 'name', 'credential_type']);

        return view('livewire.tools.create-tool-form', [
            'types' => $types,
            'builtInKinds' => BuiltInToolKind::cases(),
            'riskLevels' => ToolRiskLevel::cases(),
            'sshCredentials' => $sshCredentials,
            'availableCredentials' => $availableCredentials,
        ])->layout('layouts.app', ['header' => 'Create Tool']);
    }
}
