<?php

namespace Database\Seeders;

use App\Models\Branch;
use App\Models\Department;
use App\Models\Organization;
use App\Models\Permission;
use App\Models\Role;
use App\Models\SystemSetting;
use App\Models\User;
use App\Models\UserAssignment;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;

class DatabaseSeeder extends Seeder
{
    use WithoutModelEvents;

    public function run(): void
    {
        $organization = Organization::query()->updateOrCreate(
            ['code' => 'NESTAB'],
            ['name' => 'NESTAB SECURITY GPS', 'legal_name' => 'NESTAB, Lda.', 'is_active' => true],
        );

        $luanda = Branch::query()->updateOrCreate(
            ['code' => 'LAD-SEDE'],
            [
                'organization_id' => $organization->id,
                'name' => 'Sede — Luanda',
                'type' => 'sede',
                'province' => 'Luanda',
                'municipality' => 'Luanda',
                'is_headquarters' => true,
                'is_active' => true,
            ],
        );

        Branch::query()->updateOrCreate(
            ['code' => 'HLA-LBG'],
            [
                'organization_id' => $organization->id,
                'parent_id' => $luanda->id,
                'name' => 'Filial — Huíla/Lubango',
                'type' => 'filial',
                'province' => 'Huíla',
                'municipality' => 'Lubango',
                'is_headquarters' => false,
                'is_active' => true,
            ],
        );

        $departments = [
            'direccao-geral' => 'Direcção Geral',
            'assessoria-estrategica-operacional' => 'Assessoria Estratégica e Operacional',
            'comercial-marketing' => 'Comercial e Marketing',
            'gestao-clientes' => 'Gestão de Clientes',
            'financeiro' => 'Financeiro',
            'tecnico' => 'Departamento Técnico',
            'ti' => 'Tecnologias de Informação',
            'administrativo' => 'Administrativo',
            'rh' => 'Recursos Humanos',
        ];

        foreach ($departments as $code => $name) {
            Department::query()->updateOrCreate(
                ['organization_id' => $organization->id, 'code' => $code],
                ['name' => $name, 'is_active' => true],
            );
        }

        $permissionDefinitions = [
            ['foundation.view', 'fundacao', 'consultar', 'Consultar Fundação'],
            ['organizations.manage', 'organizacao', 'gerir', 'Gerir organização'],
            ['branches.manage', 'filiais', 'gerir', 'Gerir filiais'],
            ['departments.manage', 'departamentos', 'gerir', 'Gerir departamentos'],
            ['users.manage', 'utilizadores', 'gerir', 'Gerir utilizadores'],
            ['roles.manage', 'acessos', 'gerir', 'Gerir perfis e permissões'],
            ['audit.view', 'auditoria', 'consultar', 'Consultar auditoria'],
            ['settings.manage', 'configuracoes', 'gerir', 'Gerir configurações'],
            ['imports.manage', 'importacoes', 'gerir', 'Gerir importações'],
            ['search.use', 'pesquisa', 'consultar', 'Utilizar pesquisa global'],
        ];

        $permissions = collect($permissionDefinitions)->mapWithKeys(function (array $definition): array {
            [$code, $module, $action, $name] = $definition;
            $permission = Permission::query()->updateOrCreate(
                ['code' => $code],
                compact('module', 'action', 'name'),
            );
            return [$code => $permission];
        });

        $roles = [
            'superadministrador' => ['Superadministrador', true, true],
            'administrador' => ['Administrador', true, true],
            'direccao' => ['Direcção', false, true],
            'assessoria' => ['Assessoria', false, true],
            'chefia' => ['Chefia', false, true],
            'operador' => ['Operador', false, true],
            'consulta' => ['Consulta', false, true],
        ];

        foreach ($roles as $code => [$name, $privileged, $system]) {
            Role::query()->updateOrCreate(
                ['code' => $code],
                ['name' => $name, 'is_privileged' => $privileged, 'is_system' => $system, 'is_active' => true],
            );
        }

        Role::query()->where('code', 'assessoria')->firstOrFail()->permissions()->sync(
            $permissions->only(['foundation.view', 'audit.view', 'imports.manage', 'search.use'])->pluck('id'),
        );
        Role::query()->where('code', 'direccao')->firstOrFail()->permissions()->sync(
            $permissions->only(['foundation.view', 'audit.view', 'search.use'])->pluck('id'),
        );
        Role::query()->where('code', 'consulta')->firstOrFail()->permissions()->sync(
            $permissions->only(['foundation.view', 'search.use'])->pluck('id'),
        );

        foreach ([
            ['security', 'normal_session_minutes', '120', 'integer', 'Duração da sessão normal em minutos'],
            ['security', 'administration_session_minutes', '60', 'integer', 'Duração do Modo de Administração em minutos'],
            ['security', 'maximum_login_attempts', '5', 'integer', 'Tentativas falhadas antes do bloqueio'],
            ['system', 'default_operating_mode', 'operation', 'string', 'Modo de entrada por defeito'],
        ] as [$group, $key, $value, $type, $description]) {
            SystemSetting::query()->updateOrCreate(['key' => $key], compact('group', 'value', 'type', 'description'));
        }

        $bootstrap = config('nestab.bootstrap_superadmin');
        if (! empty($bootstrap['email']) && ! empty($bootstrap['password'])) {
            $user = User::query()->updateOrCreate(
                ['email' => $bootstrap['email']],
                [
                    'name' => $bootstrap['name'],
                    'username' => 'joselany.francisco',
                    'password' => Hash::make($bootstrap['password']),
                    'is_active' => true,
                    'must_change_password' => true,
                ],
            );

            $assessoria = Department::query()->where('code', 'assessoria-estrategica-operacional')->firstOrFail();
            foreach ([
                ['role' => 'assessoria', 'primary' => true],
                ['role' => 'superadministrador', 'primary' => false],
            ] as $assignment) {
                UserAssignment::query()->updateOrCreate(
                    [
                        'user_id' => $user->id,
                        'organization_id' => $organization->id,
                        'branch_id' => null,
                        'department_id' => $assessoria->id,
                        'role_id' => Role::query()->where('code', $assignment['role'])->value('id'),
                    ],
                    ['is_primary' => $assignment['primary'], 'is_active' => true],
                );
            }
        }
    }
}
