<?php

declare(strict_types=1);

namespace ImovelZapAi\Automation\Presentation\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
use ImovelZapAi\Automation\Application\Actions\ActivateWorkflowAction;
use ImovelZapAi\Automation\Application\Actions\CreateWorkflowAction;
use ImovelZapAi\Automation\Application\Actions\InstallWorkflowTemplateAction;
use ImovelZapAi\Automation\Application\Actions\PauseWorkflowAction;
use ImovelZapAi\Automation\Application\Actions\SeedAutomationTemplatesAction;
use ImovelZapAi\Automation\Application\Actions\UpdateWorkflowAction;
use ImovelZapAi\Automation\Application\Queries\GetAutomationDashboardQuery;
use ImovelZapAi\Automation\Application\Queries\ListExecutionsQuery;
use ImovelZapAi\Automation\Application\Queries\ListWorkflowsQuery;
use ImovelZapAi\Automation\Application\Services\TriggerCatalog;
use ImovelZapAi\Automation\Domain\Exceptions\AutomationException;
use ImovelZapAi\Automation\Infrastructure\Persistence\Eloquent\AutomationTemplateModel;
use ImovelZapAi\Automation\Infrastructure\Persistence\Eloquent\AutomationWorkflowModel;
use ImovelZapAi\Tenancy\Support\TenantContext;

final class AutomationWebController extends Controller
{
    public function index(
        GetAutomationDashboardQuery $dashboard,
        ListWorkflowsQuery $workflows,
    ): View {
        $tenantId = (string) TenantContext::id();

        return view('automation.index', [
            'dashboard' => $dashboard->execute($tenantId),
            'workflows' => $workflows->execute($tenantId, ['per_page' => 20]),
        ]);
    }

    public function create(TriggerCatalog $catalog): View
    {
        return view('automation.form', [
            'workflow' => null,
            'triggers' => $catalog->listTriggers(),
            'actionOptions' => $catalog->listActions(),
            'operators' => $catalog->listOperators(),
        ]);
    }

    public function edit(string $workflow, TriggerCatalog $catalog): View
    {
        $model = AutomationWorkflowModel::query()
            ->with(['triggers', 'conditions', 'actions'])
            ->findOrFail($workflow);

        return view('automation.form', [
            'workflow' => $model,
            'triggers' => $catalog->listTriggers(),
            'actionOptions' => $catalog->listActions(),
            'operators' => $catalog->listOperators(),
        ]);
    }

    public function show(string $workflow, ListExecutionsQuery $executions): View
    {
        $model = AutomationWorkflowModel::query()
            ->with(['triggers', 'conditions', 'actions'])
            ->findOrFail($workflow);

        $tenantId = (string) TenantContext::id();

        return view('automation.show', [
            'workflow' => $model,
            'executions' => $executions->execute($tenantId, [
                'workflow_id' => $model->id,
                'per_page' => 20,
            ]),
        ]);
    }

    public function templates(SeedAutomationTemplatesAction $seed): View
    {
        try {
            $seed->execute();
        } catch (\Throwable) {
            // Migração ainda não aplicada neste ambiente.
        }

        return view('automation.templates', [
            'templates' => AutomationTemplateModel::query()
                ->where('is_active', true)
                ->orderBy('category')
                ->orderBy('name')
                ->get(),
            'triggerLabels' => collect(app(TriggerCatalog::class)->listTriggers())
                ->mapWithKeys(fn (array $t): array => [$t['key'] => $t['label']])
                ->all(),
            'actionLabels' => collect(app(TriggerCatalog::class)->listActions())
                ->mapWithKeys(fn (array $a): array => [$a['key'] => $a['label']])
                ->all(),
        ]);
    }

    public function store(Request $request, CreateWorkflowAction $action): RedirectResponse
    {
        $data = $this->validatedWorkflow($request);

        try {
            $workflow = $action->execute((string) TenantContext::id(), $request->user(), $data);
        } catch (AutomationException $e) {
            return back()->withInput()->with('error', $e->getMessage());
        }

        return redirect()
            ->route('automation.show', $workflow->id)
            ->with('success', 'Automação criada.');
    }

    public function update(string $workflow, Request $request, UpdateWorkflowAction $action): RedirectResponse
    {
        $data = $this->validatedWorkflow($request);

        try {
            $model = $action->execute((string) TenantContext::id(), $workflow, $data);
        } catch (AutomationException $e) {
            return back()->withInput()->with('error', $e->getMessage());
        }

        return redirect()
            ->route('automation.show', $model->id)
            ->with('success', 'Automação atualizada.');
    }

    public function activate(string $workflow, ActivateWorkflowAction $action): RedirectResponse
    {
        try {
            $action->execute((string) TenantContext::id(), $workflow);
        } catch (AutomationException $e) {
            return back()->with('error', $e->getMessage());
        }

        return back()->with('success', 'Automação ativada.');
    }

    public function pause(string $workflow, PauseWorkflowAction $action): RedirectResponse
    {
        try {
            $action->execute((string) TenantContext::id(), $workflow);
        } catch (AutomationException $e) {
            return back()->with('error', $e->getMessage());
        }

        return back()->with('success', 'Automação pausada.');
    }

    public function installTemplate(string $slug, InstallWorkflowTemplateAction $action): RedirectResponse
    {
        try {
            $workflow = $action->execute((string) TenantContext::id(), request()->user(), $slug, true);
        } catch (AutomationException $e) {
            return back()->with('error', $e->getMessage());
        } catch (\Throwable $e) {
            report($e);

            return back()->with('error', 'Não foi possível instalar o modelo. Tente novamente.');
        }

        return redirect()
            ->route('automation.show', $workflow->id)
            ->with('status', 'Modelo instalado e ativado. A automação passa a responder aos eventos configurados.');
    }

    /** @return array<string, mixed> */
    private function validatedWorkflow(Request $request): array
    {
        return $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'description' => ['nullable', 'string'],
            'status' => ['nullable', 'string'],
            'trigger.event_key' => ['required', 'string'],
            'trigger.config' => ['nullable', 'array'],
            'conditions' => ['nullable', 'array'],
            'conditions.*.field' => ['required_with:conditions', 'string'],
            'conditions.*.operator' => ['required_with:conditions', 'string'],
            'conditions.*.value' => ['nullable', 'string'],
            'actions' => ['nullable', 'array'],
            'actions.*.action_key' => ['required_with:actions', 'string'],
            'actions.*.config' => ['nullable', 'array'],
            'actions.*.delay_seconds' => ['nullable', 'integer', 'min:0'],
        ]);
    }
}
