<?php
/**
 * Flexia — espacios compartidos del explorador (comunitario y por departamento).
 *
 * - Comunitario: media/explorer/files (todos los usuarios con acceso).
 * - Departamento: media/explorer/departments/{deptId}/files (solo miembros del departamento).
 */

if (!function_exists('grid_explorer_shared_spaces_defaults')) {
  /**
   * @return array{community: array<string, mixed>, departments: array<string, mixed>}
   */
  function grid_explorer_shared_spaces_defaults(): array
  {
    return [
      'community' => [
        'enabled' => true,
        'displayName' => 'Espacio comunitario',
        'hiddenForUserIds' => [],
      ],
      'departments' => [
        'enabled' => true,
        'hiddenForUserIds' => [],
      ],
    ];
  }
}

if (!function_exists('grid_explorer_shared_spaces_normalize')) {
  /**
   * @param mixed $raw
   * @return array{community: array<string, mixed>, departments: array<string, mixed>}
   */
  function grid_explorer_shared_spaces_normalize($raw): array
  {
    $def = grid_explorer_shared_spaces_defaults();
    if (!is_array($raw)) {
      return $def;
    }
    $out = $def;
    foreach (['community', 'departments'] as $key) {
      if (!isset($raw[$key]) || !is_array($raw[$key])) {
        continue;
      }
      $src = $raw[$key];
      if (array_key_exists('enabled', $src)) {
        $out[$key]['enabled'] = !empty($src['enabled']);
      }
      if ($key === 'community' && isset($src['displayName'])) {
        $name = trim((string) $src['displayName']);
        if ($name !== '') {
          if (function_exists('mb_substr')) {
            $name = (string) mb_substr($name, 0, 120, 'UTF-8');
          } elseif (strlen($name) > 120) {
            $name = substr($name, 0, 120);
          }
          $out['community']['displayName'] = $name;
        }
      }
      if (isset($src['hiddenForUserIds']) && is_array($src['hiddenForUserIds'])) {
        $ids = [];
        foreach ($src['hiddenForUserIds'] as $uid) {
          $uid = trim((string) $uid);
          if ($uid !== '') {
            $ids[$uid] = true;
          }
        }
        $out[$key]['hiddenForUserIds'] = array_keys($ids);
      }
    }

    return $out;
  }
}

if (!function_exists('grid_explorer_shared_actor')) {
  /**
   * @return array{id: string, role: string, branchId: string, departmentId: string}
   */
  function grid_explorer_shared_actor(): array
  {
    $id = '';
    $role = '';
    $branchId = '';
    $departmentId = '';
    if (!class_exists('AntaraSession', false)) {
      require_once dirname(__DIR__) . '/core/auth/session.php';
    }
    if (AntaraSession::isLoggedIn()) {
      $u = AntaraSession::user();
      if (is_array($u)) {
        $id = trim((string) ($u['id'] ?? ''));
        $role = trim((string) ($u['role'] ?? ''));
      }
    }
    if ($id !== '' && class_exists('AntaraStore', false)) {
      try {
        $fresh = AntaraStore::findUserById($id);
        if ($fresh) {
          $role = trim((string) ($fresh['role'] ?? $role));
          $branchId = trim((string) ($fresh['branchId'] ?? ''));
          $departmentId = trim((string) ($fresh['departmentId'] ?? ''));
        }
      } catch (\Throwable $e) {
      }
    }

    return [
      'id' => $id,
      'role' => $role,
      'branchId' => $branchId,
      'departmentId' => $departmentId,
    ];
  }
}

if (!function_exists('grid_explorer_shared_is_admin_role')) {
  function grid_explorer_shared_is_admin_role(string $role): bool
  {
    if (!class_exists('AntaraStore', false)) {
      require_once dirname(__DIR__) . '/core/auth/store.php';
    }

    return in_array($role, [AntaraStore::ROLE_SUPER, AntaraStore::ROLE_ADMIN], true);
  }
}

if (!function_exists('grid_explorer_community_files_base')) {
  function grid_explorer_community_files_base(): string
  {
    $root = defined('GRID_ROOT') && is_string(GRID_ROOT) && GRID_ROOT !== ''
      ? GRID_ROOT
      : dirname(__DIR__);

    return $root . DIRECTORY_SEPARATOR . 'media' . DIRECTORY_SEPARATOR . 'explorer' . DIRECTORY_SEPARATOR . 'files';
  }
}

if (!function_exists('grid_explorer_department_files_base')) {
  function grid_explorer_department_files_base(string $departmentId): string
  {
    if (!function_exists('antara_settings_valid_department_id')) {
      require_once __DIR__ . '/settings_helpers.php';
    }
    $departmentId = preg_replace('/[^a-zA-Z0-9_\-]/', '', $departmentId);
    if ($departmentId === '') {
      throw new InvalidArgumentException('Invalid department id');
    }
    $root = defined('GRID_ROOT') && is_string(GRID_ROOT) && GRID_ROOT !== ''
      ? GRID_ROOT
      : dirname(__DIR__);

    return $root . DIRECTORY_SEPARATOR . 'media' . DIRECTORY_SEPARATOR . 'explorer'
      . DIRECTORY_SEPARATOR . 'departments' . DIRECTORY_SEPARATOR . $departmentId
      . DIRECTORY_SEPARATOR . 'files';
  }
}

if (!function_exists('grid_explorer_ensure_community_dir')) {
  function grid_explorer_ensure_community_dir(): void
  {
    $dir = grid_explorer_community_files_base();
    if (!is_dir($dir)) {
      @mkdir($dir, 0755, true);
    }
  }
}

if (!function_exists('grid_explorer_ensure_department_dir')) {
  function grid_explorer_ensure_department_dir(string $departmentId): void
  {
    $dir = grid_explorer_department_files_base($departmentId);
    if (!is_dir($dir)) {
      @mkdir($dir, 0755, true);
    }
  }
}

if (!function_exists('grid_explorer_ensure_all_department_dirs')) {
  /** @param array<string, mixed> $settings */
  function grid_explorer_ensure_all_department_dirs(array $settings): void
  {
    $branches = isset($settings['branches']) && is_array($settings['branches']) ? $settings['branches'] : [];
    foreach ($branches as $branch) {
      if (!is_array($branch)) {
        continue;
      }
      $departments = isset($branch['departments']) && is_array($branch['departments']) ? $branch['departments'] : [];
      foreach ($departments as $dept) {
        if (!is_array($dept)) {
          continue;
        }
        $deptId = trim((string) ($dept['id'] ?? ''));
        if ($deptId === '') {
          continue;
        }
        grid_explorer_ensure_department_dir($deptId);
      }
    }
  }
}

if (!function_exists('grid_explorer_find_department')) {
  /**
   * @param array<string, mixed> $settings
   * @return array{branchId: string, id: string, name: string}|null
   */
  function grid_explorer_find_department(array $settings, string $departmentId): ?array
  {
    if ($departmentId === '') {
      return null;
    }
    $branches = isset($settings['branches']) && is_array($settings['branches']) ? $settings['branches'] : [];
    foreach ($branches as $branch) {
      if (!is_array($branch)) {
        continue;
      }
      $branchId = trim((string) ($branch['id'] ?? ''));
      $departments = isset($branch['departments']) && is_array($branch['departments']) ? $branch['departments'] : [];
      foreach ($departments as $dept) {
        if (!is_array($dept)) {
          continue;
        }
        if ((string) ($dept['id'] ?? '') === $departmentId) {
          return [
            'branchId' => $branchId,
            'id' => $departmentId,
            'name' => trim((string) ($dept['name'] ?? 'Departamento')),
          ];
        }
      }
    }

    return null;
  }
}

if (!function_exists('grid_explorer_shared_hidden_for_actor')) {
  /** @param array<string, mixed> $spaceCfg */
  function grid_explorer_shared_hidden_for_actor(array $spaceCfg, string $userId): bool
  {
    if ($userId === '') {
      return false;
    }
    $hidden = isset($spaceCfg['hiddenForUserIds']) && is_array($spaceCfg['hiddenForUserIds'])
      ? $spaceCfg['hiddenForUserIds'] : [];

    return in_array($userId, $hidden, true);
  }
}

if (!function_exists('grid_explorer_can_access_community')) {
  /** @param array<string, mixed> $settings */
  function grid_explorer_can_access_community(array $settings, array $actor): bool
  {
    $cfg = grid_explorer_shared_spaces_normalize($settings['explorerSharedSpaces'] ?? null);
    if (empty($cfg['community']['enabled'])) {
      return false;
    }
    if (grid_explorer_shared_is_admin_role($actor['role'] ?? '')) {
      return true;
    }
    if (trim((string) ($actor['id'] ?? '')) === '') {
      return false;
    }
    if (grid_explorer_shared_hidden_for_actor($cfg['community'], (string) $actor['id'])) {
      return false;
    }

    return true;
  }
}

if (!function_exists('grid_explorer_can_access_department')) {
  /** @param array<string, mixed> $settings */
  function grid_explorer_can_access_department(array $settings, array $actor, string $departmentId): bool
  {
    if (!class_exists('AntaraStore', false)) {
      require_once dirname(__DIR__) . '/core/auth/store.php';
    }
    $departmentId = trim($departmentId);
    if ($departmentId === '') {
      return false;
    }
    $dept = grid_explorer_find_department($settings, $departmentId);
    if ($dept === null) {
      return false;
    }
    $cfg = grid_explorer_shared_spaces_normalize($settings['explorerSharedSpaces'] ?? null);
    if (empty($cfg['departments']['enabled'])) {
      return false;
    }
    if (grid_explorer_shared_is_admin_role($actor['role'] ?? '')) {
      if (($actor['role'] ?? '') === AntaraStore::ROLE_SUPER) {
        return true;
      }
      $actorBranch = trim((string) ($actor['branchId'] ?? ''));

      return $actorBranch === '' || $actorBranch === ($dept['branchId'] ?? '');
    }
    if (trim((string) ($actor['id'] ?? '')) === '') {
      return false;
    }
    if (grid_explorer_shared_hidden_for_actor($cfg['departments'], (string) $actor['id'])) {
      return false;
    }

    return trim((string) ($actor['departmentId'] ?? '')) === $departmentId;
  }
}

if (!function_exists('grid_explorer_visible_departments_for_actor')) {
  /**
   * @param array<string, mixed> $settings
   * @return list<array{id: string, name: string, branchId: string}>
   */
  function grid_explorer_visible_departments_for_actor(array $settings, array $actor): array
  {
    if (!class_exists('AntaraStore', false)) {
      require_once dirname(__DIR__) . '/core/auth/store.php';
    }
    $cfg = grid_explorer_shared_spaces_normalize($settings['explorerSharedSpaces'] ?? null);
    if (empty($cfg['departments']['enabled'])) {
      return [];
    }
    $out = [];
    $branches = isset($settings['branches']) && is_array($settings['branches']) ? $settings['branches'] : [];
    $isSuper = ($actor['role'] ?? '') === AntaraStore::ROLE_SUPER;
    $isAdmin = ($actor['role'] ?? '') === AntaraStore::ROLE_ADMIN;
    $actorBranch = trim((string) ($actor['branchId'] ?? ''));
    $actorDept = trim((string) ($actor['departmentId'] ?? ''));
    $hidden = grid_explorer_shared_hidden_for_actor($cfg['departments'], (string) ($actor['id'] ?? ''));

    foreach ($branches as $branch) {
      if (!is_array($branch)) {
        continue;
      }
      $branchId = trim((string) ($branch['id'] ?? ''));
      $departments = isset($branch['departments']) && is_array($branch['departments']) ? $branch['departments'] : [];
      foreach ($departments as $dept) {
        if (!is_array($dept)) {
          continue;
        }
        $deptId = trim((string) ($dept['id'] ?? ''));
        if ($deptId === '') {
          continue;
        }
        if ($hidden && !$isSuper && !$isAdmin) {
          continue;
        }
        if ($isSuper) {
          $out[] = ['id' => $deptId, 'name' => trim((string) ($dept['name'] ?? 'Departamento')), 'branchId' => $branchId];
          continue;
        }
        if ($isAdmin) {
          if ($actorBranch === '' || $actorBranch === $branchId) {
            $out[] = ['id' => $deptId, 'name' => trim((string) ($dept['name'] ?? 'Departamento')), 'branchId' => $branchId];
          }
          continue;
        }
        if ($actorDept === $deptId) {
          $out[] = ['id' => $deptId, 'name' => trim((string) ($dept['name'] ?? 'Departamento')), 'branchId' => $branchId];
        }
      }
    }

    return $out;
  }
}

if (!function_exists('grid_explorer_shared_spaces_payload_for_actor')) {
  /** @param array<string, mixed> $settings */
  function grid_explorer_shared_spaces_payload_for_actor(array $settings, array $actor): array
  {
    $cfg = grid_explorer_shared_spaces_normalize($settings['explorerSharedSpaces'] ?? null);
    $canManage = grid_explorer_shared_is_admin_role($actor['role'] ?? '');

    return [
      'community' => [
        'visible' => grid_explorer_can_access_community($settings, $actor),
        'displayName' => (string) ($cfg['community']['displayName'] ?? 'Espacio comunitario'),
        'enabled' => !empty($cfg['community']['enabled']),
        'hiddenForUserIds' => $canManage ? array_values($cfg['community']['hiddenForUserIds']) : [],
      ],
      'departments' => [
        'visibleList' => grid_explorer_visible_departments_for_actor($settings, $actor),
        'enabled' => !empty($cfg['departments']['enabled']),
        'hiddenForUserIds' => $canManage ? array_values($cfg['departments']['hiddenForUserIds']) : [],
      ],
      'canManage' => $canManage,
      'canRenameCommunity' => grid_explorer_can_access_community($settings, $actor),
    ];
  }
}

if (!function_exists('grid_explorer_resolve_storage_context')) {
  /**
   * @param array<string, mixed> $input
   * @param array<string, mixed> $settings
   * @return array{ok: bool, error?: string, bucket?: string, departmentId?: string, baseDir?: string, urlPrefix?: string}
   */
  function grid_explorer_resolve_storage_context(array $input, array $settings): array
  {
    if (!function_exists('grid_explorer_local_files_base')) {
      require_once __DIR__ . '/user_settings_helpers.php';
    }
    $bucket = isset($input['bucket']) ? (string) $input['bucket'] : 'files';
    $departmentId = isset($input['departmentId']) ? trim((string) $input['departmentId']) : '';
    $actor = grid_explorer_shared_actor();

    if ($bucket === 'community') {
      if (!grid_explorer_can_access_community($settings, $actor)) {
        return ['ok' => false, 'error' => 'Sin acceso al espacio comunitario'];
      }
      grid_explorer_ensure_community_dir();

      return [
        'ok' => true,
        'bucket' => 'community',
        'departmentId' => '',
        'baseDir' => grid_explorer_community_files_base(),
        'urlPrefix' => 'media/explorer/files/',
      ];
    }

    if ($bucket === 'department') {
      if (!grid_explorer_can_access_department($settings, $actor, $departmentId)) {
        return ['ok' => false, 'error' => 'Sin acceso a este departamento'];
      }
      grid_explorer_ensure_department_dir($departmentId);

      return [
        'ok' => true,
        'bucket' => 'department',
        'departmentId' => $departmentId,
        'baseDir' => grid_explorer_department_files_base($departmentId),
        'urlPrefix' => 'media/explorer/departments/' . rawurlencode($departmentId) . '/files/',
      ];
    }

    if ($bucket === 'cache') {
      return [
        'ok' => true,
        'bucket' => 'cache',
        'departmentId' => '',
        'baseDir' => grid_explorer_local_base_dir('cache'),
        'urlPrefix' => 'media/explorer/remote-cache/',
      ];
    }

    if ($bucket === 'files') {
      require_once __DIR__ . '/flexia_disk.php';

      return grid_flexia_disk_files_storage_context($input, $actor);
    }

    return ['ok' => false, 'error' => 'Bucket no soportado'];
  }
}

if (!function_exists('grid_explorer_restore_base_dir')) {
  function grid_explorer_restore_base_dir(string $bucket, string $departmentId = ''): string
  {
    if ($bucket === 'community') {
      grid_explorer_ensure_community_dir();

      return grid_explorer_community_files_base();
    }
    if ($bucket === 'department' && $departmentId !== '') {
      grid_explorer_ensure_department_dir($departmentId);

      return grid_explorer_department_files_base($departmentId);
    }
    if (!function_exists('grid_explorer_local_base_dir')) {
      require_once __DIR__ . '/user_settings_helpers.php';
    }

    return grid_explorer_local_base_dir($bucket === 'cache' ? 'cache' : 'files');
  }
}

if (!function_exists('grid_explorer_shared_spaces_apply_patch')) {
  /**
   * @param array<string, mixed> $settings
   * @param array<string, mixed> $patch
   * @param array<string, mixed> $actor
   * @return array{ok: bool, error?: string, settings?: array<string, mixed>}
   */
  function grid_explorer_shared_spaces_apply_patch(array $settings, array $patch, array $actor): array
  {
    $cfg = grid_explorer_shared_spaces_normalize($settings['explorerSharedSpaces'] ?? null);
    $canManage = grid_explorer_shared_is_admin_role($actor['role'] ?? '');

    if (isset($patch['communityDisplayName'])) {
      if (!grid_explorer_can_access_community($settings, $actor)) {
        return ['ok' => false, 'error' => 'Sin permiso para renombrar el espacio comunitario'];
      }
      $name = trim((string) $patch['communityDisplayName']);
      if ($name === '') {
        return ['ok' => false, 'error' => 'Nombre no válido'];
      }
      if (function_exists('mb_substr')) {
        $name = (string) mb_substr($name, 0, 120, 'UTF-8');
      } elseif (strlen($name) > 120) {
        $name = substr($name, 0, 120);
      }
      $cfg['community']['displayName'] = $name;
    }

    if ($canManage) {
      if (isset($patch['communityEnabled'])) {
        $cfg['community']['enabled'] = !empty($patch['communityEnabled']);
      }
      if (isset($patch['departmentsEnabled'])) {
        $cfg['departments']['enabled'] = !empty($patch['departmentsEnabled']);
      }
      if (isset($patch['communityHiddenForUserIds']) && is_array($patch['communityHiddenForUserIds'])) {
        $cfg['community']['hiddenForUserIds'] = array_values(array_unique(array_filter(array_map('strval', $patch['communityHiddenForUserIds']))));
      }
      if (isset($patch['departmentsHiddenForUserIds']) && is_array($patch['departmentsHiddenForUserIds'])) {
        $cfg['departments']['hiddenForUserIds'] = array_values(array_unique(array_filter(array_map('strval', $patch['departmentsHiddenForUserIds']))));
      }
    } elseif (isset($patch['communityEnabled']) || isset($patch['departmentsEnabled'])
      || isset($patch['communityHiddenForUserIds']) || isset($patch['departmentsHiddenForUserIds'])) {
      return ['ok' => false, 'error' => 'Solo administradores pueden cambiar la visibilidad'];
    }

    $settings['explorerSharedSpaces'] = $cfg;

    return ['ok' => true, 'settings' => $settings];
  }
}
