import os

def to_camel_case(text):
    words = text.split()
    return words[0].lower() + ''.join(word.capitalize() for word in words[1:])

def criar_arquivos_crud(nome_tabela, 
                        colunas, 
                        menu_grupo, 
                        titulo_pagina, 
                        termino_o_a,
                        titulo_singular,
                        titulo_plural):

    # Normaliza o nome da tabela para o padrão PascalCase
    nome_normalizado = ''.join([palavra.capitalize()
                               for palavra in nome_tabela.split('_')])
    nome_url = '-'.join([palavra.lower()
                        for palavra in nome_tabela.split('_')])
    
    msg_validacao = 'Nenhuma' if termino_o_a == 'a' else 'Nenhum'

    titulo_minusculo = titulo_pagina.strip().lower()
    titulo_primeira_letra_maiuscula = titulo_minusculo.capitalize()

    titulo_minusculo_singular = titulo_singular.lower()
    titulo_minusculo_plural = titulo_plural.lower()

    titulo_primeira_letra_maiuscula_singular = titulo_minusculo_singular.capitalize()

    objeto_nome = nome_normalizado[0].lower() + nome_normalizado[1:]

    # Diretório base do projeto Laravel
    base_dir = '../Backoffice_Marketplace'

    # Caminhos para Model, Controller, Request, Repository e Provider
    model_dir = os.path.join(base_dir, 'app', 'Models')
    controller_dir = os.path.join(base_dir, 'app', 'Http', 'Controllers')
    request_dir = os.path.join(base_dir, 'app', 'Http', 'Requests')
    repository_dir = os.path.join(base_dir, 'app', 'Repositories')
    provider_dir = os.path.join(base_dir, 'app', 'Providers')
    views_dir = os.path.join(base_dir, 'resources', 'views', nome_tabela)

    # Função auxiliar para criar diretórios, se não existirem
    def criar_diretorio(diretorio):
        if not os.path.exists(diretorio):
            os.makedirs(diretorio)

    # Criar todos os diretórios necessários
    criar_diretorio(model_dir)
    criar_diretorio(controller_dir)
    criar_diretorio(request_dir)
    criar_diretorio(repository_dir)
    criar_diretorio(provider_dir)
    criar_diretorio(views_dir)

    colunas_formatadas = ',\n        '.join([f"'{coluna}'" for coluna in colunas])

    # Arquivo Model (com as modificações pedidas)
    model_file = os.path.join(model_dir, f'{nome_normalizado}.php')
    with open(model_file, 'w', encoding='utf-8') as f:
        f.write(f"""<?php

namespace App\\Models;

use Illuminate\\Database\\Eloquent\\Factories\\HasFactory;
use Illuminate\\Database\\Eloquent\\Model;
use Illuminate\\Database\\Eloquent\\SoftDeletes;
use Shared\\Domain\\Traits\\UuidTrait;

class {nome_normalizado} extends Model
{{
    use HasFactory, SoftDeletes, UuidTrait;

    protected $table = '{nome_tabela}';

    protected $fillable = [
        {colunas_formatadas}
    ];

    protected $dates = [
        'created_at',
        'updated_at',
        'deleted_at'
    ];

    protected static function boot()
    {{
        parent::boot();
        static::bootUuidTrait();
    }}
}}
""")

    # Arquivo Controller
    controller_file = os.path.join(
        controller_dir, f'{nome_normalizado}Controller.php')
    with open(controller_file, 'w', encoding='utf-8') as f:
        f.write(f"""<?php

namespace App\\Http\\Controllers;

use App\\Exceptions\\CustomException;
use App\\Http\\Controllers\\Controller;
use App\\Http\\Requests\\{nome_normalizado}Request;
use App\\Repositories\\{nome_normalizado}RepositoryInterface;
use Illuminate\\Http\\RedirectResponse;
use Illuminate\\Http\\Request;
use Illuminate\\View\\View;
use Throwable;

class {nome_normalizado}Controller extends Controller
{{
    public function __construct(
        private {nome_normalizado}RepositoryInterface $repository,
    ) {{
        parent::__construct();
        $this->breadcrumbs->addCrumb('{menu_grupo}', '/{nome_url}');
        $this->breadcrumbs->addCrumb('{titulo_primeira_letra_maiuscula}', '');

        $this->setActivePages([
            '{nome_tabela}' => '{nome_url}'
        ]);
        $this->setCurrentPage($this->determineActivePage());
    }}

    public function index(Request $request): View | RedirectResponse
    {{
        try {{
            $search = [ /* criteria */ ];

            $trashed = $request->has('trashed');
            $page = $request->query('page', 1);
            $perPage = $request->query('per_page', 15);

            ${objeto_nome} = $this->repository->search($search, $trashed, $page, $perPage);

            return view('{nome_tabela}.index', [
                '{objeto_nome}' => ${objeto_nome},
                'trashed' => $trashed,
                'perPage' => $perPage
            ]);
        }} catch (CustomException $e) {{
            report($e);
            return redirect()->route('{nome_tabela}.index')->with('error', $e->getMessage());
        }}
    }}

    public function all(): View | RedirectResponse
    {{
        try {{
            ${objeto_nome} = $this->repository->getAll();

            return view('{nome_tabela}.index', [
                '{objeto_nome}' => ${objeto_nome}
            ]);
        }} catch (CustomException $e) {{
            report($e);
            return redirect()
                ->route('{nome_tabela}.index')
                ->with('error', $e->getMessage());
        }} catch (Throwable $e) {{
            report($e);
            return redirect()
                ->route('{nome_tabela}.index')
                ->with('error', 'Falha ao obter tod{termino_o_a}s {termino_o_a}s {titulo_minusculo_plural}.');
        }}
    }}

    public function create(): View | RedirectResponse
    {{
        $this->breadcrumbs->add('Criar', route('{nome_tabela}.create'));

        try {{
            return view('{nome_tabela}.create');
        }} catch (CustomException $e) {{
            report($e);
            return redirect()
                ->route('{nome_tabela}.index')
                ->with('error', $e->getMessage());
        }} catch (Throwable $e) {{
            report($e);
            return redirect()
                ->route('{nome_tabela}.index')
                ->with('error', 'Falha ao criar {termino_o_a} {titulo_minusculo_singular}.');
        }}
    }}

    public function store({nome_normalizado}Request $request): RedirectResponse
    {{
        try {{
            $data = $request->all();
            $response = $this->repository->create($data);

            return redirect()
                ->route('{nome_tabela}.edit', $response->uuid)
                ->with('success', '{titulo_primeira_letra_maiuscula_singular} criad{termino_o_a} com sucesso.');
        }} catch (CustomException $e) {{
            report($e);
            return redirect()
                ->route('{nome_tabela}.index')
                ->with('error', $e->getMessage());
        }} catch (Throwable $e) {{
            report($e);
            return redirect()
                ->route('{nome_tabela}.index')
                ->with('error', 'Falha ao armazenar {termino_o_a} {titulo_minusculo_singular}.');
        }}
    }}

    public function edit(string $uuid): View | RedirectResponse
    {{
        try {{
            ${objeto_nome} = $this->repository->find($uuid);

            $this->breadcrumbs->add(${objeto_nome}['name'], '/edit');

            return view('{nome_tabela}.edit', [
                '{objeto_nome}' => ${objeto_nome}
            ]);
        }} catch (CustomException $e) {{
            report($e);
            return redirect()
                ->route('{nome_tabela}.index')
                ->with('error', $e->getMessage());
        }} catch (Throwable $e) {{
            report($e);
            return redirect()
                ->route('{nome_tabela}.index')
                ->with('error', 'Falha ao editar {termino_o_a} {titulo_minusculo_singular}.');
        }}
    }}

    public function update({nome_normalizado}Request $request, string $uuid): RedirectResponse
    {{
        try {{
            $data = $request->all();
            ${objeto_nome} = $this->repository->find($uuid);

            $data['table_name'] = ${objeto_nome}->getTable();
            $data['id'] = ${objeto_nome}->id;

            $this->repository->update($uuid, $data);

            return redirect()
                ->route('{nome_tabela}.index')
                ->with('success', '{titulo_primeira_letra_maiuscula_singular} atualizad{termino_o_a} com sucesso.');
        }} catch (CustomException $e) {{
            report($e);
            return redirect()
                ->route('{nome_tabela}.index')
                ->with('error', $e->getMessage());
        }} catch (Throwable $e) {{
            report($e);
            return redirect()
                ->route('{nome_tabela}.index')
                ->with('error', 'Falha ao atualizar {termino_o_a} {titulo_minusculo_singular}.');
        }}
    }}

    public function destroy(string $uuid): RedirectResponse
    {{
        try {{
            $this->repository->delete($uuid);

            return redirect()
                ->route('{nome_tabela}.index')
                ->with('success', '{titulo_primeira_letra_maiuscula_singular} eliminad{termino_o_a} com sucesso.');
        }} catch (CustomException $e) {{
            report($e);
            return redirect()
                ->route('{nome_tabela}.index')
                ->with('error', $e->getMessage());
        }} catch (Throwable $e) {{
            report($e);
            return redirect()
                ->route('{nome_tabela}.index')
                ->with('error', 'Falha ao eliminar {termino_o_a} {titulo_minusculo_singular}.');
        }}
    }}

    public function restore(string $uuid): RedirectResponse
    {{
        try {{
            $this->repository->restore($uuid);

            return redirect()
                ->route('{nome_tabela}.index')
                ->with('success', '{titulo_primeira_letra_maiuscula_singular} restaurad{termino_o_a} com sucesso.');
        }} catch (CustomException $e) {{
            report($e);
            return redirect()
                ->route('{nome_tabela}.index')
                ->with('error', $e->getMessage());
        }} catch (Throwable $e) {{
            report($e);
            return redirect()
                ->route('{nome_tabela}.index')
                ->with('error', 'Falha ao restaurar {termino_o_a} {titulo_minusculo_singular}.');
        }}
    }}

    public function forceDelete(string $uuid): RedirectResponse
    {{
        try {{
            $this->repository->forceDelete($uuid);

            return redirect()
                ->route('{nome_tabela}.index')
                ->with('success', '{titulo_primeira_letra_maiuscula_singular} eliminad{termino_o_a} permanentemente com sucesso.');
        }} catch (CustomException $e) {{
            report($e);
            return redirect()
                ->route('{nome_tabela}.index')
                ->with('error', $e->getMessage());
        }} catch (Throwable $e) {{
            report($e);
            return redirect()
                ->route('{nome_tabela}.index')
                ->with('error', 'Falha ao eliminar permanentemente {termino_o_a} {titulo_minusculo_singular}.');
        }}
    }}
}}
""")
        
    regras_validacao = ',\n            '.join([f"'{coluna}' => 'required'" for coluna in colunas])
    mensagens_validacao = ',\n            '.join(
        [f"'{coluna}.required' => 'O campo é obrigatório.'" for coluna in colunas]
    )

    regras_validacao = ',\n            '.join([f"'{coluna}' => 'required'" for coluna in colunas])
    mensagens_validacao = ',\n            '.join(
        [f"'{coluna}.required' => 'O campo é obrigatório.'" for coluna in colunas]
    )

    # Arquivo Request com validação e mensagens personalizadas
    request_file = os.path.join(request_dir, f'{nome_normalizado}Request.php')
    with open(request_file, 'w', encoding='utf-8') as f:
        f.write(f"""<?php

namespace App\\Http\\Requests;

use Illuminate\\Foundation\\Http\\FormRequest;

class {nome_normalizado}Request extends FormRequest
{{
    public function authorize(): bool
    {{
        return true;
    }}

    public function rules(): array
    {{
        return [
            {regras_validacao}
        ];
    }}

    public function messages(): array
    {{
        return [
            {mensagens_validacao}
        ];
    }}
}}
""")

    # Arquivo Repository Interface (com tipagem)
    repository_interface_file = os.path.join(
        repository_dir, f'{nome_normalizado}RepositoryInterface.php')
    with open(repository_interface_file, 'w', encoding='utf-8') as f:
        f.write(f"""<?php

namespace App\\Repositories;

use App\\Models\\{nome_normalizado};
use Illuminate\\Support\\Collection;
use Illuminate\\Pagination\\LengthAwarePaginator;

interface {nome_normalizado}RepositoryInterface
{{
    public function getAll(): Collection;
    public function find(string $uuid): {nome_normalizado};
    public function create(array $data): {nome_normalizado};
    public function update(string $uuid, array $data): {nome_normalizado};
    public function delete(string $uuid): bool;
    public function restore(string $uuid): {nome_normalizado};
    public function forceDelete(string $uuid): bool;
    public function search(array $criteria = [], ?bool $trashed = null, int $page = 1, int $perPage = 15): LengthAwarePaginator;
    public function getFiltered(array $filters): Collection;
}}
""")

    # Arquivo Repository Implementação (com tipagem)
    repository_impl_file = os.path.join(
        repository_dir, f'{nome_normalizado}Repository.php')
    with open(repository_impl_file, 'w', encoding='utf-8') as f:
        f.write(f"""<?php

namespace App\\Repositories;

use App\\Models\\{nome_normalizado};
use App\\Exceptions\\CustomException;
use App\\Traits\\FilterTrait;
use Illuminate\\Database\\Eloquent\\Collection;
use Illuminate\\Pagination\\LengthAwarePaginator;
use Throwable;

class {nome_normalizado}Repository implements {nome_normalizado}RepositoryInterface
{{
    use FilterTrait;

    public function __construct(
        protected {nome_normalizado} $model
    )
    {{}}

    public function getAll(): Collection
    {{
        ${objeto_nome} = $this->model->get();

        if (!${objeto_nome}) {{
            throw new CustomException('{msg_validacao} {titulo_minusculo_singular} foi encontrad{termino_o_a}.', 404);
        }}

        return ${objeto_nome};
    }}

    public function find(string $uuid): {nome_normalizado}
    {{
        ${objeto_nome} = $this->model->uuid($uuid)->first();

        if (!${objeto_nome}) {{
            throw new CustomException('{termino_o_a.upper()} {titulo_minusculo_singular} não foi encontrad{termino_o_a}.', 404);
        }}

        return ${objeto_nome};
    }}

    public function create(array $data): {nome_normalizado}
    {{
        return $this->model->create($data);
    }}

    public function update(string $uuid, array $data): {nome_normalizado}
    {{
        ${objeto_nome} = $this->model->uuid($uuid)->first();

        if (!${objeto_nome}) {{
            throw new CustomException('{termino_o_a.upper()} {titulo_minusculo_singular} não foi encontrad{termino_o_a}.', 404);
        }}

        ${objeto_nome}->update($data);
        return ${objeto_nome};
    }}

    public function delete(string $uuid): bool
    {{
        ${objeto_nome} = $this->model->uuid($uuid)->first();

        if (!${objeto_nome}) {{
            throw new CustomException('{termino_o_a.upper()} {titulo_minusculo_singular} não foi encontrad{termino_o_a}.', 404);
        }}

        ${objeto_nome}->delete();

        return true;
    }}

    public function restore(string $uuid): {nome_normalizado}
    {{
        ${objeto_nome} = $this->model->withTrashed()->uuid($uuid)->first();

        if (!${objeto_nome}) {{
            throw new CustomException('{termino_o_a.upper()} {titulo_minusculo_singular} não pode ser restaurad{termino_o_a}.', 400);
        }}

        ${objeto_nome}->restore();
        return ${objeto_nome};
    }}

    public function forceDelete(string $uuid): bool
    {{
        ${objeto_nome} = $this->model->withTrashed()->uuid($uuid)->firstOrFail();

        return ${objeto_nome}->forceDelete();
    }}

    public function search(array $criteria = [], ?bool $trashed = null, int $page = 1, int $perPage = 15): LengthAwarePaginator
    {{
        $query = $this->model;

        if ($trashed) {{
            $query->onlyTrashed();
        }}

        return $query->paginate($perPage, ['*'], 'page', $page);
    }}

    public function getFiltered(array $filters = []): Collection
    {{
        return $this->applyFilters($this->model, $filters);
    }}
}}
""")

    # Arquivo ServiceProvider
    provider_file = os.path.join(
        provider_dir, f'{nome_normalizado}ServiceProvider.php')
    with open(provider_file, 'w', encoding='utf-8') as f:
        f.write(f"""<?php

namespace App\\Providers;

use Illuminate\\Support\\ServiceProvider;
use App\\Repositories\\{nome_normalizado}RepositoryInterface;
use App\\Repositories\\{nome_normalizado}Repository;

class {nome_normalizado}ServiceProvider extends ServiceProvider
{{
    public function register()
    {{
        $this->app->bind({nome_normalizado}RepositoryInterface::class, {nome_normalizado}Repository::class);
    }}

    public function boot()
    {{
        //
    }}
}}
""")

    # Views padrão fornecidas
    view_files = {
        'index.blade.php': f"""@extends('layouts.partials.master')

@section('title', '{titulo_pagina}')

@push('styles')
    <link href="{{{{asset('assets/css/forms.css')}}}}" rel="stylesheet" type="text/css">
    <link href="{{{{asset('assets/css/tables.css')}}}}" rel="stylesheet" type="text/css">
    <link href="{{{{asset('assets/css/cards.css')}}}}" rel="stylesheet" type="text/css">
    <link href="{{{{asset('assets/css/badges.css')}}}}" rel="stylesheet" type="text/css">
@endpush

@section('content')
<nav aria-label="breadcrumb">
    {{!! $breadcrumbs !!}}
</nav>
    @include('layouts.components.section-title', ['title' => '{titulo_pagina}'])

    {{{{-- filters --}}}}
    <div class="card py-4 px-4">
        <form action="{{{{ route('{nome_tabela}.index') }}}}" method="GET">
            <div class="row mb-3">

            </div>
            <div class="row">
                <div class="col">
                    <div class="form-check">
                        <input type="checkbox" name="trashed" class="form-check-input" id="trashed" {{{{ request('trashed') ? 'checked' : '' }}}}>
                        <label class="form-check-label" for="trashed">Excluídos</label>
                    </div>
                </div>
                <div class="col text-end">
                    <button type="submit" class="btn btn-sm btn-primary">Filtrar <i class="fa-light fa-filters"></i></button>
                    <button type="button" class="btn btn-sm btn-primary" id="clearFormButton">Limpar <i class="fa-light fa-xmark"></i></button>
                </div>
            </div>
        </form>
    </div>

    @include('layouts.components.alerts')

    <div class="d-flex justify-content-between align-items-center mt-1 mb-3">
        <div>
            <a class="btn btn-sm btn-primary mt-5 mb-4" href="{{{{ route('{nome_tabela}.create') }}}}">Adicionar <i class="fa-light fa-plus"></i></a>
            @if (${objeto_nome} instanceof \Illuminate\Pagination\LengthAwarePaginator)
                <a href="{{{{ route('{nome_tabela}.all') }}}}" class="btn btn-sm btn-primary mt-5 mb-4">Ver todos <i class="fa-light fa-list-ul"></i></a>
            @else
                <a href="{{{{ route('{nome_tabela}.index') }}}}" class="btn btn-sm btn-primary mt-5 mb-4">Paginar <i class="fa-light fa-list-ol"></i></a>
            @endif
        </div>

        @include('layouts.components.per-page', ['subject' => ${objeto_nome}, 'route' => '{nome_tabela}'])
    </div>

    <div class="d-flex flex-column gap-4 mb-2">
        <div class="row g-4">
            <div class="col-12">
                <div class="card">
                    <div class="table-responsive">
                        <table class="table table-borderless fs-12">
                            <thead>
                                <tr>
                                    <th class="text-left">ID</th>
                                    <th class="text-left fit">Ações</th>
                                </tr>
                            </thead>
                            <tbody>

                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>
    @include('layouts.components.pagination', ['subject' => ${objeto_nome}])
@endsection
""",
        'create.blade.php': f"""@extends('layouts.partials.master')

@section('title', 'Criar {titulo_primeira_letra_maiuscula_singular}')

@push('styles')
    <link href="{{{{asset('assets/css/forms.css')}}}}" rel="stylesheet" type="text/css">
    <link href="{{{{asset('assets/css/section-marker.css')}}}}" rel="stylesheet" type="text/css">
@endpush

@section('content')
<nav aria-label="breadcrumb">
    {{!! $breadcrumbs !!}}
</nav>

    <div class="d-flex justify-content-between align-items-center my-4">
        @include('layouts.components.section-title', ['title' => 'Criar {titulo_primeira_letra_maiuscula_singular}'])
        <a href="{{{{ url('{nome_url}') }}}}" class="btn btn-sm btn-primary">Voltar <i class="fa-light fa-left-from-line"></i></a>
    </div>

    <form action="{{{{ route('{nome_tabela}.store') }}}}" method="POST">
        @csrf
        @method('POST')
        <div class="card py-4 px-4">
            <div class="row mb-3">

            </div>
        </div>

        <div class="row my-4">
            <div class="col-12 text-end">
                <button type="submit" class="btn btn-sm btn-primary">Gravar <i class="fa-light fa-floppy-disk"></i></button>
            </div>
        </div>
    </form>
@endsection
""",
        'edit.blade.php': f"""@extends('layouts.partials.master')

@section('title', 'Editar {titulo_primeira_letra_maiuscula_singular}')

@push('styles')
    <link href="{{{{asset('assets/css/forms.css')}}}}" rel="stylesheet" type="text/css">
    <link href="{{{{asset('assets/css/section-marker.css')}}}}" rel="stylesheet" type="text/css">
@endpush

@section('content')
<nav aria-label="breadcrumb">
    {{!! $breadcrumbs !!}}
</nav>

    <div class="d-flex justify-content-between align-items-center my-4">
        @include('layouts.components.section-title', ['title' => 'Editar {titulo_primeira_letra_maiuscula_singular}'])
        <a href="{{{{ url('{nome_url}') }}}}" class="btn btn-sm btn-primary">Voltar <i class="fa-light fa-left-from-line"></i></a>
    </div>

    @include('layouts.components.alerts')

    <form action="{{{{ route('{nome_tabela}.update', ${objeto_nome}->uuid) }}}}" method="POST">
        @csrf
        @method('PUT')

        <div class="card py-4 px-4">
            <div class="row mb-3">

            </div>
        </div>

        <div class="row my-4">
            <div class="col-12 text-end">
                <button type="submit" class="btn btn-sm btn-primary">Gravar <i class="fa-light fa-floppy-disk"></i></button>
            </div>
        </div>
    </form>
@endsection
"""
    }

    for view, content in view_files.items():
        view_file = os.path.join(views_dir, view)
        with open(view_file, 'w', encoding='utf-8') as f:
            f.write(content)

    print(f"\nMódulo CRUD para {nome_tabela} criado com sucesso!\n")
    print(f"Não esqueça de incluir o provider gerado em \\bootstrap\\providers.php (App\\Providers\\{nome_normalizado}ServiceProvider::class)\n")
    print(f"Segue a rota para incluir em \\routes\\web.php")
    print(f"""
        Route::prefix('{nome_url}')->group(function () {{
            Route::get('/', [{nome_normalizado}Controller::class, 'index'])->name('{nome_tabela}.index');
            Route::get('/all', [{nome_normalizado}Controller::class, 'all'])->name('{nome_tabela}.all');
            Route::get('/create', [{nome_normalizado}Controller::class, 'create'])->name('{nome_tabela}.create');
            Route::get('/{{uuid}}/edit', [{nome_normalizado}Controller::class, 'edit'])->name('{nome_tabela}.edit');
            Route::delete('/{{uuid}}', [{nome_normalizado}Controller::class, 'destroy'])->name('{nome_tabela}.destroy');
            Route::post('/', [{nome_normalizado}Controller::class, 'store'])->name('{nome_tabela}.store');
            Route::put('/{{uuid}}', [{nome_normalizado}Controller::class, 'update'])->name('{nome_tabela}.update');
            Route::post('/{{uuid}}/restore', [{nome_normalizado}Controller::class, 'restore'])->name('{nome_tabela}.restore');
            Route::delete('/{{uuid}}/forceDelete', [{nome_normalizado}Controller::class, 'forceDelete'])->name('{nome_tabela}.forceDelete');
        }});
    """)

# Solicita informações adicionais ao usuário
menu_grupo = input("Digite o nome do menu pai: ").strip()
titulo_pagina = input("Digite o título da página: ").strip()
termino_o_a = input("Título é masculino ou feminino: responda 'o' ou 'a'? ").strip().lower()
titulo_singlar = input("Digite o título da página no singular: ").strip().lower()
titulo_plural = input("Digite o título da página no plural: ").strip().lower()

# Solicita o nome da tabela e as colunas
tabela = input("Digite o nome da tabela: ").strip()
colunas = input("Digite os nomes das colunas separados por vírgula: ").split(',')

# Limpa os nomes das colunas
colunas = [coluna.strip() for coluna in colunas]

# Cria arquivos CRUD com as informações fornecidas
criar_arquivos_crud(
    tabela,
    colunas,
    menu_grupo,
    titulo_pagina,
    termino_o_a,
    titulo_singlar,
    titulo_plural
)

