<?php

namespace MintyPHP\Service\User;

use MintyPHP\Repository\Tenant\UserTenantRepositoryInterface;
use MintyPHP\Repository\User\UserReadRepositoryInterface;
use MintyPHP\Repository\User\UserWriteRepositoryInterface;
use MintyPHP\Service\Tenant\TenantScopeService;

class UserTenantContextService
{
    public function __construct(
        private readonly UserReadRepositoryInterface $userReadRepository,
        private readonly UserWriteRepositoryInterface $userWriteRepository,
        private readonly UserTenantRepositoryInterface $userTenantRepository,
        private readonly TenantScopeService $scopeGateway,
        private readonly UserDirectoryGateway $directoryGateway
    ) {
    }

    /**
     * Get the current tenant ID for a user (with fallback to primary tenant)
     */
    public function getCurrentTenantId(int $userId): ?int
    {
        $user = $this->userReadRepository->find($userId);
        if (!$user) {
            return null;
        }

        $activeTenantIds = $this->scopeGateway->getUserTenantIds($userId);
        if (!$activeTenantIds) {
            return null;
        }

        // Priority: last-used tenant → primary tenant → first available.
        $currentTenantId = (int) ($user['current_tenant_id'] ?? 0);
        if ($currentTenantId > 0 && in_array($currentTenantId, $activeTenantIds, true)) {
            return $currentTenantId;
        }

        $primaryTenantId = (int) ($user['primary_tenant_id'] ?? 0);
        if ($primaryTenantId > 0 && in_array($primaryTenantId, $activeTenantIds, true)) {
            return $primaryTenantId;
        }

        return $activeTenantIds[0] ?? null;
    }

    /**
     * Get the current tenant data for a user
     */
    public function getCurrentTenant(int $userId): ?array
    {
        $currentTenantId = $this->getCurrentTenantId($userId);
        if (!$currentTenantId) {
            return null;
        }

        return $this->directoryGateway->findTenant($currentTenantId);
    }

    /**
     * Get all tenants the user has access to
     */
    public function getAvailableTenants(int $userId): array
    {
        $tenantIds = $this->scopeGateway->getUserTenantIds($userId);
        if (!$tenantIds) {
            return [];
        }

        $tenants = [];
        foreach ($tenantIds as $tenantId) {
            $tenant = $this->directoryGateway->findTenant((int) $tenantId);
            if ($tenant && (($tenant['status'] ?? 'active') === 'active')) {
                $tenants[] = $tenant;
            }
        }

        usort($tenants, static function ($a, $b) {
            return strcmp((string) ($a['description'] ?? ''), (string) ($b['description'] ?? ''));
        });

        return $tenants;
    }

    /**
     * Get only explicitly assigned active tenants for a user.
     * This intentionally ignores global tenant-scope bypass permissions.
     */
    public function getAssignedActiveTenants(int $userId): array
    {
        if ($userId <= 0) {
            return [];
        }

        $tenantIds = array_values(array_unique(array_map(
            'intval',
            $this->userTenantRepository->listTenantIdsByUserId($userId)
        )));
        $tenantIds = array_values(array_filter($tenantIds, static fn ($id) => $id > 0));
        if (!$tenantIds) {
            return [];
        }

        $activeTenantIds = $this->directoryGateway->listActiveTenantIdsByIds($tenantIds);
        if (!$activeTenantIds) {
            return [];
        }

        $tenantsById = [];
        foreach ($this->directoryGateway->listTenantsByIds($activeTenantIds) as $tenant) {
            $tenantId = (int) ($tenant['id'] ?? 0);
            if ($tenantId <= 0) {
                continue;
            }
            $tenantsById[$tenantId] = $tenant;
        }

        $tenants = [];
        foreach ($tenantIds as $tenantId) {
            if (isset($tenantsById[$tenantId])) {
                $tenants[] = $tenantsById[$tenantId];
            }
        }

        usort($tenants, static function ($a, $b) {
            return strcmp((string) ($a['description'] ?? ''), (string) ($b['description'] ?? ''));
        });

        return $tenants;
    }

    /**
     * Set the current tenant for a user (with validation)
     */
    public function setCurrentTenant(int $userId, int $tenantId): array
    {
        if ($tenantId <= 0) {
            return ['ok' => false, 'error' => 'invalid_tenant'];
        }

        $userTenantIds = $this->userTenantRepository->listTenantIdsByUserId($userId);
        if (!in_array($tenantId, $userTenantIds, true)) {
            return ['ok' => false, 'error' => 'tenant_not_assigned'];
        }

        $tenant = $this->directoryGateway->findTenant($tenantId);
        if (!$tenant) {
            return ['ok' => false, 'error' => 'tenant_not_found'];
        }
        if (($tenant['status'] ?? 'active') !== 'active') {
            return ['ok' => false, 'error' => 'tenant_inactive'];
        }

        $updated = $this->userWriteRepository->setCurrentTenant($userId, $tenantId);
        if (!$updated) {
            return ['ok' => false, 'error' => 'update_failed'];
        }

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