<?php

namespace Blueprint\Generators\Statements;

use Blueprint\Blueprint;
use Blueprint\Generators\StatementGenerator;
use Blueprint\Models\Statements\SendStatement;
use Blueprint\Tree;

class NotificationGenerator extends StatementGenerator
{
    protected $types = ['controllers'];

    public function output(Tree $tree): array
    {
        $stub = $this->filesystem->stub('notification.stub');

        /**
         * @var \Blueprint\Models\Controller $controller
         */
        foreach ($tree->controllers() as $controller) {
            foreach ($controller->methods() as $method => $statements) {
                foreach ($statements as $statement) {
                    if (!$statement instanceof SendStatement) {
                        continue;
                    }

                    if (!$statement->isNotification()) {
                        continue;
                    }

                    $path = $this->getStatementPath($statement->mail());

                    if ($this->filesystem->exists($path)) {
                        continue;
                    }

                    $this->create($path, $this->populateStub($stub, $statement));
                }
            }
        }

        return $this->output;
    }

    protected function getStatementPath(string $name)
    {
        return Blueprint::appPath() . '/Notification/' . $name . '.php';
    }

    protected function populateStub(string $stub, SendStatement $sendStatement)
    {
        $stub = str_replace('{{ namespace }}', config('blueprint.namespace') . '\\Notification', $stub);
        $stub = str_replace('{{ class }}', $sendStatement->mail(), $stub);
        $stub = str_replace('{{ properties }}', $this->populateConstructor('message', $sendStatement), $stub);

        if (Blueprint::useReturnTypeHints()) {
            $stub = str_replace(
                [
                    'via($notifiable)',
                    'toMail($notifiable)',
                    'toArray($notifiable)',
                ],
                [
                    'via($notifiable): array',
                    sprintf('toMail($notifiable): %s', $sendStatement->mail()),
                    'toArray($notifiable): array',
                ],
                $stub
            );
        }

        return $stub;
    }
}
