<?php
/**
 * Estructura organizacional por sucursal: departamentos y puestos.
 * Cada sucursal define su propio catálogo (branches[].departments[]).
 */

require_once __DIR__ . '/settings_helpers.php';

if (!function_exists('antara_org_is_company_mode')) {
    function antara_org_is_company_mode(array $settings): bool
    {
        return ($settings['deploymentKind'] ?? '') === 'company';
    }
}

if (!function_exists('antara_org_new_id')) {
    function antara_org_new_id(string $prefix): string
    {
        if (!class_exists('AntaraStore', false)) {
            require_once dirname(__DIR__) . '/core/auth/store.php';
        }
        $raw = str_replace('-', '', AntaraStore::uuid());

        return preg_replace('/[^a-zA-Z0-9_]/', '', $prefix) . '_' . $raw;
    }
}

if (!function_exists('antara_org_sanitize_label')) {
    function antara_org_sanitize_label(string $label, int $max = 120): string
    {
        $label = trim(preg_replace('/\s+/u', ' ', $label) ?? '');
        if ($label === '') {
            return '';
        }
        if (function_exists('mb_substr')) {
            return (string) mb_substr($label, 0, $max, 'UTF-8');
        }

        return substr($label, 0, $max);
    }
}

if (!function_exists('antara_org_normalize_position')) {
    /**
     * @param array<string, mixed> $pos
     * @return array{id: string, name: string}|null
     */
    function antara_org_normalize_position(array $pos): ?array
    {
        $name = antara_org_sanitize_label((string) ($pos['name'] ?? ''));
        if ($name === '') {
            return null;
        }
        $id = preg_replace('/[^a-zA-Z0-9_\-]/', '', (string) ($pos['id'] ?? ''));
        if ($id === '') {
            $id = antara_org_new_id('pos');
        }

        return ['id' => $id, 'name' => $name];
    }
}

if (!function_exists('antara_org_normalize_department')) {
    /**
     * @param array<string, mixed> $dept
     * @return array{id: string, name: string, positions: list<array{id: string, name: string}>}|null
     */
    function antara_org_normalize_department(array $dept): ?array
    {
        $name = antara_org_sanitize_label((string) ($dept['name'] ?? ''));
        if ($name === '') {
            return null;
        }
        $id = preg_replace('/[^a-zA-Z0-9_\-]/', '', (string) ($dept['id'] ?? ''));
        if ($id === '') {
            $id = antara_org_new_id('dept');
        }
        $positions = [];
        $seenPos = [];
        foreach ($dept['positions'] ?? [] as $p) {
            if (!is_array($p)) {
                continue;
            }
            $norm = antara_org_normalize_position($p);
            if ($norm === null || isset($seenPos[$norm['id']])) {
                continue;
            }
            $seenPos[$norm['id']] = true;
            $positions[] = $norm;
        }

        return ['id' => $id, 'name' => $name, 'positions' => $positions];
    }
}

if (!function_exists('antara_org_normalize_branch')) {
    /**
     * @param array<string, mixed> $branch
     * @return array<string, mixed>
     */
    function antara_org_normalize_branch(array $branch): array
    {
        $departments = [];
        $seenDept = [];
        foreach ($branch['departments'] ?? [] as $d) {
            if (!is_array($d)) {
                continue;
            }
            $norm = antara_org_normalize_department($d);
            if ($norm === null || isset($seenDept[$norm['id']])) {
                continue;
            }
            $seenDept[$norm['id']] = true;
            $departments[] = $norm;
        }
        $branch['departments'] = $departments;

        return $branch;
    }
}

if (!function_exists('antara_org_normalize_branches')) {
    /**
     * @param list<array<string, mixed>> $branches
     * @return list<array<string, mixed>>
     */
    function antara_org_normalize_branches(array $branches): array
    {
        $out = [];
        foreach ($branches as $b) {
            if (!is_array($b)) {
                continue;
            }
            $out[] = antara_org_normalize_branch($b);
        }

        return $out;
    }
}

if (!function_exists('antara_org_find_branch')) {
    /**
     * @return array<string, mixed>|null
     */
    function antara_org_find_branch(array $settings, string $branchId): ?array
    {
        if ($branchId === '') {
            return null;
        }
        foreach ($settings['branches'] ?? [] as $b) {
            if (is_array($b) && (string) ($b['id'] ?? '') === $branchId) {
                return antara_org_normalize_branch($b);
            }
        }

        return null;
    }
}

if (!function_exists('antara_org_department_exists')) {
    function antara_org_department_exists(array $branch, string $departmentId): bool
    {
        if ($departmentId === '') {
            return false;
        }
        foreach ($branch['departments'] ?? [] as $d) {
            if (is_array($d) && (string) ($d['id'] ?? '') === $departmentId) {
                return true;
            }
        }

        return false;
    }
}

if (!function_exists('antara_org_position_exists')) {
    function antara_org_position_exists(array $branch, string $departmentId, string $positionId): bool
    {
        if ($departmentId === '' || $positionId === '') {
            return false;
        }
        foreach ($branch['departments'] ?? [] as $d) {
            if (!is_array($d) || (string) ($d['id'] ?? '') !== $departmentId) {
                continue;
            }
            foreach ($d['positions'] ?? [] as $p) {
                if (is_array($p) && (string) ($p['id'] ?? '') === $positionId) {
                    return true;
                }
            }
        }

        return false;
    }
}

if (!function_exists('antara_org_validate_user_fields')) {
    /**
     * Valida departmentId/positionId contra la sucursal indicada.
     *
     * @return string|null Mensaje de error o null si es válido
     */
    function antara_org_validate_user_fields(array $settings, string $branchId, string $departmentId, string $positionId): ?string
    {
        $departmentId = trim($departmentId);
        $positionId = trim($positionId);

        if ($departmentId === '' && $positionId === '') {
            return null;
        }
        if ($branchId === '') {
            return 'Indica la sucursal antes de asignar departamento o puesto.';
        }
        $branch = antara_org_find_branch($settings, $branchId);
        if ($branch === null) {
            return 'Sucursal no válida.';
        }
        if ($departmentId === '') {
            return 'Indica el departamento cuando asignes un puesto.';
        }
        if (!antara_org_department_exists($branch, $departmentId)) {
            return 'Departamento no válido para esta sucursal.';
        }
        if ($positionId !== '' && !antara_org_position_exists($branch, $departmentId, $positionId)) {
            return 'Puesto no válido para el departamento seleccionado.';
        }

        return null;
    }
}

if (!function_exists('antara_org_resolve_labels')) {
    /**
     * @return array{department: string, position: string, branch: string}
     */
    function antara_org_resolve_labels(array $settings, string $branchId, string $departmentId, string $positionId): array
    {
        $out = ['department' => '', 'position' => '', 'branch' => ''];
        foreach ($settings['branches'] ?? [] as $b) {
            if (!is_array($b) || (string) ($b['id'] ?? '') !== $branchId) {
                continue;
            }
            $out['branch'] = (string) ($b['name'] ?? $branchId);
            $branch = antara_org_normalize_branch($b);
            foreach ($branch['departments'] ?? [] as $d) {
                if (!is_array($d) || (string) ($d['id'] ?? '') !== $departmentId) {
                    continue;
                }
                $out['department'] = (string) ($d['name'] ?? '');
                foreach ($d['positions'] ?? [] as $p) {
                    if (is_array($p) && (string) ($p['id'] ?? '') === $positionId) {
                        $out['position'] = (string) ($p['name'] ?? '');
                        break;
                    }
                }
                break;
            }
            break;
        }

        return $out;
    }
}

if (!function_exists('antara_org_public_branches')) {
    /**
     * Catálogo seguro para el panel admin (solo id, name, departments).
     *
     * @param list<array<string, mixed>> $branches
     * @return list<array<string, mixed>>
     */
    function antara_org_public_branches(array $branches): array
    {
        $out = [];
        foreach (antara_org_normalize_branches($branches) as $b) {
            $out[] = [
                'id' => (string) ($b['id'] ?? ''),
                'name' => (string) ($b['name'] ?? ''),
                'code' => (string) ($b['code'] ?? ''),
                'departments' => $b['departments'] ?? [],
            ];
        }

        return $out;
    }
}

if (!function_exists('antara_org_parse_departments_payload')) {
    /**
     * @param mixed $raw
     * @return list<array{id: string, name: string, positions: list<array{id: string, name: string}>}>
     */
    function antara_org_parse_departments_payload($raw): array
    {
        if (!is_array($raw)) {
            return [];
        }
        $departments = [];
        $seen = [];
        foreach ($raw as $item) {
            if (!is_array($item)) {
                continue;
            }
            $norm = antara_org_normalize_department($item);
            if ($norm === null || isset($seen[$norm['id']])) {
                continue;
            }
            $seen[$norm['id']] = true;
            $departments[] = $norm;
        }

        return $departments;
    }
}

if (!function_exists('antara_org_apply_branch_departments')) {
    /**
     * @param array<string, mixed> $settings
     * @param list<array<string, mixed>> $departments
     * @return array{settings: array<string, mixed>, error: string|null}
     */
    function antara_org_apply_branch_departments(array $settings, string $branchId, array $departments): array
    {
        if ($branchId === '' || !antara_settings_valid_branch_id($settings, $branchId)) {
            return ['settings' => $settings, 'error' => 'Sucursal no válida.'];
        }
        $normalized = antara_org_parse_departments_payload($departments);
        $branches = $settings['branches'] ?? [];
        $found = false;
        foreach ($branches as $i => $b) {
            if (!is_array($b) || (string) ($b['id'] ?? '') !== $branchId) {
                continue;
            }
            $branches[$i] = array_merge($b, ['departments' => $normalized]);
            $found = true;
            break;
        }
        if (!$found) {
            return ['settings' => $settings, 'error' => 'Sucursal no encontrada.'];
        }
        $settings['branches'] = $branches;
        require_once __DIR__ . '/explorer_shared_spaces.php';
        grid_explorer_ensure_all_department_dirs($settings);

        return ['settings' => $settings, 'error' => null];
    }
}

if (!function_exists('antara_workspace_persist_settings')) {
    function antara_workspace_persist_settings(array $settings): bool
    {
        if (!function_exists('grid_app_default_settings')) {
            require_once __DIR__ . '/grid_default_settings.php';
        }
        $def = grid_app_default_settings();
        $merged = grid_merge_settings_defaults($def, $settings);
        $root = defined('GRID_ROOT') && is_string(GRID_ROOT) && GRID_ROOT !== ''
            ? GRID_ROOT
            : (defined('ANTARA_ROOT') && is_string(ANTARA_ROOT) ? ANTARA_ROOT : dirname(__DIR__));
        $sf = $root . DIRECTORY_SEPARATOR . 'settings.json';
        $bk = $root . DIRECTORY_SEPARATOR . 'settings.json.bak';

        return grid_persist_settings($sf, $bk, $merged);
    }
}
