<?php

namespace MintyPHP\Service\User;

use MintyPHP\Service\Access\RoleService;
use MintyPHP\Service\Org\DepartmentService;
use MintyPHP\Service\Tenant\TenantService;

final class UserApiWriteInputMapper
{
    public function __construct(
        private readonly TenantService $tenantService,
        private readonly RoleService $roleService,
        private readonly DepartmentService $departmentService
    ) {
    }

    /**
     * Normalize public UUID-based assignment payload to internal IDs used by services.
     *
     * @param array<string, mixed> $input
     * @return array{ok: bool, input?: array<string, mixed>, errors?: array<string, array<int, string>>}
     */
    public function normalize(array $input): array
    {
        $errors = [];
        foreach ([
            'tenant_ids' => 'use_tenant_uuids',
            'primary_tenant_id' => 'use_primary_tenant_uuid',
            'role_ids' => 'use_role_uuids',
            'department_ids' => 'use_department_uuids',
        ] as $legacyKey => $errorCode) {
            if (array_key_exists($legacyKey, $input)) {
                $errors[$legacyKey] = [$errorCode];
            }
        }
        if ($errors) {
            return ['ok' => false, 'errors' => $errors];
        }

        $normalizeUuidList = static function (mixed $raw): array {
            $values = is_array($raw) ? $raw : [$raw];
            $uuids = [];
            foreach ($values as $value) {
                $uuid = trim((string) $value);
                if ($uuid !== '') {
                    $uuids[] = $uuid;
                }
            }
            return array_values(array_unique($uuids));
        };

        if (array_key_exists('tenant_uuids', $input)) {
            $tenantUuids = $normalizeUuidList($input['tenant_uuids']);
            $tenantIds = [];
            foreach ($tenantUuids as $tenantUuid) {
                $tenant = $this->tenantService->findByUuid($tenantUuid);
                if (!$tenant) {
                    $errors['tenant_uuids'][] = 'not_found';
                    continue;
                }
                $tenantId = (int) ($tenant['id'] ?? 0);
                if ($tenantId > 0) {
                    $tenantIds[] = $tenantId;
                }
            }
            $input['tenant_ids'] = array_values(array_unique($tenantIds));
            unset($input['tenant_uuids']);
        }

        if (array_key_exists('primary_tenant_uuid', $input)) {
            $primaryTenantUuid = trim((string) ($input['primary_tenant_uuid'] ?? ''));
            if ($primaryTenantUuid === '') {
                $input['primary_tenant_id'] = 0;
            } else {
                $primaryTenant = $this->tenantService->findByUuid($primaryTenantUuid);
                if (!$primaryTenant) {
                    $errors['primary_tenant_uuid'][] = 'not_found';
                } else {
                    $input['primary_tenant_id'] = (int) ($primaryTenant['id'] ?? 0);
                }
            }
            unset($input['primary_tenant_uuid']);
        }

        if (array_key_exists('role_uuids', $input)) {
            $roleUuids = $normalizeUuidList($input['role_uuids']);
            $roleIds = [];
            foreach ($roleUuids as $roleUuid) {
                $role = $this->roleService->findByUuid($roleUuid);
                if (!$role) {
                    $errors['role_uuids'][] = 'not_found';
                    continue;
                }
                $roleId = (int) ($role['id'] ?? 0);
                if ($roleId > 0) {
                    $roleIds[] = $roleId;
                }
            }
            $input['role_ids'] = array_values(array_unique($roleIds));
            unset($input['role_uuids']);
        }

        if (array_key_exists('department_uuids', $input)) {
            $departmentUuids = $normalizeUuidList($input['department_uuids']);
            $departmentIds = [];
            foreach ($departmentUuids as $departmentUuid) {
                $department = $this->departmentService->findByUuid($departmentUuid);
                if (!$department) {
                    $errors['department_uuids'][] = 'not_found';
                    continue;
                }
                $departmentId = (int) ($department['id'] ?? 0);
                if ($departmentId > 0) {
                    $departmentIds[] = $departmentId;
                }
            }
            $input['department_ids'] = array_values(array_unique($departmentIds));
            unset($input['department_uuids']);
        }

        if ($errors) {
            return ['ok' => false, 'errors' => $errors];
        }

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