<?php

namespace MintyPHP\Repository\Org;

use MintyPHP\DB;
use MintyPHP\Repository\Support\RepositoryArrayHelper;

/** Queries user-department assignments and counts active/inactive users per department. */
class UserDepartmentRepository implements UserDepartmentRepositoryInterface
{
    public function listDepartmentIdsByUserId(int $userId): array
    {
        $rows = DB::select('select department_id from user_departments where user_id = ?', (string) $userId);

        return RepositoryArrayHelper::extractIds($rows, 'user_departments', 'department_id');
    }

    public function replaceForUser(int $userId, array $departmentIds): bool
    {
        DB::delete('delete from user_departments where user_id = ?', (string) $userId);
        if (!$departmentIds) {
            return true;
        }

        foreach ($departmentIds as $departmentId) {
            DB::insert(
                'insert into user_departments (user_id, department_id, created) values (?,?,NOW())',
                (string) $userId,
                (string) $departmentId
            );
        }

        return true;
    }

    public function removeInvalidForDepartment(int $departmentId): int
    {
        $query = 'delete ud from user_departments ud ' .
            'where ud.department_id = ? and not exists (' .
            'select 1 from user_tenants ut ' .
            'join departments d on d.id = ud.department_id ' .
            'where ut.user_id = ud.user_id and ut.tenant_id = d.tenant_id' .
            ')';
        $result = DB::delete($query, (string) $departmentId);
        return $result !== false ? (int) $result : 0;
    }

    public function countUsersByDepartmentIds(array $departmentIds): array
    {
        return $this->countByDepartmentIds($departmentIds, false);
    }

    public function countActiveUsersByDepartmentIds(array $departmentIds): array
    {
        return $this->countByDepartmentIds($departmentIds, true);
    }

    private function countByDepartmentIds(array $departmentIds, bool $activeOnly): array
    {
        $departmentIds = RepositoryArrayHelper::sanitizePositiveIds($departmentIds);
        if (!$departmentIds) {
            return [];
        }

        $placeholders = implode(',', array_fill(0, count($departmentIds), '?'));
        $joinUsersSql = $activeOnly ? ' join users u on u.id = ud.user_id and u.active = 1' : '';
        $rows = DB::select(
            'select ud.department_id, count(distinct ud.user_id) as user_count from user_departments ud' .
            $joinUsersSql .
            ' where ud.department_id in (' . $placeholders . ') group by ud.department_id',
            ...array_map('strval', $departmentIds)
        );

        if (!is_array($rows)) {
            return [];
        }

        $result = [];
        foreach ($rows as $row) {
            $departmentId = $this->extractIntField($row, 'department_id');
            if ($departmentId <= 0) {
                continue;
            }
            $result[$departmentId] = $this->extractIntField($row, 'user_count');
        }

        return $result;
    }

    private function extractIntField(array $row, string $field): int
    {
        foreach ($row as $value) {
            if (!is_array($value)) {
                continue;
            }
            if (array_key_exists($field, $value)) {
                return (int) $value[$field];
            }
        }
        if (array_key_exists($field, $row)) {
            return (int) $row[$field];
        }
        return 0;
    }
}
