<?php

namespace MintyPHP\Module\Helpdesk\Repository;

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

class DomainSecurityLevelRepository
{
    private const TABLE = 'helpdesk_domain_security_levels';
    private const ALLOWED_LEVELS = ['niedrig', 'normal', 'hoch', 'kritisch'];

    public function findByTenantAndDomainNo(int $tenantId, string $domainNo): ?array
    {
        if ($domainNo === '') {
            return null;
        }

        $row = DB::selectOne(
            'SELECT id, tenant_id, domain_no, security_level, note, created_by, updated_by, created_at, updated_at FROM ' . self::TABLE . ' WHERE tenant_id = ? AND domain_no = ? LIMIT 1',
            (string) $tenantId,
            $domainNo
        );

        return RepositoryArrayHelper::unwrap(is_array($row) ? $row : null, self::TABLE);
    }

    /**
     * @api Called from DomainSecurityLevelService
     * @param list<string> $domainNos
     * @return array<string, string> Map of domain_no => security_level
     */
    public function listLevelsByDomainNos(int $tenantId, array $domainNos): array
    {
        if ($domainNos === []) {
            return [];
        }

        $placeholders = implode(',', array_fill(0, count($domainNos), '?'));
        $params = [(string) $tenantId, ...array_map('strval', $domainNos)];

        $rows = DB::select(
            'SELECT domain_no, security_level FROM ' . self::TABLE . ' WHERE tenant_id = ? AND domain_no IN (' . $placeholders . ')',
            ...$params
        );

        $result = [];
        foreach (RepositoryArrayHelper::unwrapList($rows, self::TABLE) as $row) {
            $domainNo = (string) ($row['domain_no'] ?? '');
            $level = (string) ($row['security_level'] ?? 'normal');
            if ($domainNo !== '') {
                $result[$domainNo] = in_array($level, self::ALLOWED_LEVELS, true) ? $level : 'normal';
            }
        }

        return $result;
    }

    /**
     * @api Called from DomainSecurityLevelService
     * @param list<string> $domainNos
     * @return array<string, array{level: string, note: string}> Map of domain_no => {level, note}
     */
    public function listDetailsByDomainNos(int $tenantId, array $domainNos): array
    {
        if ($domainNos === []) {
            return [];
        }

        $placeholders = implode(',', array_fill(0, count($domainNos), '?'));
        $params = [(string) $tenantId, ...array_map('strval', $domainNos)];

        $rows = DB::select(
            'SELECT domain_no, security_level, note FROM ' . self::TABLE . ' WHERE tenant_id = ? AND domain_no IN (' . $placeholders . ')',
            ...$params
        );

        $result = [];
        foreach (RepositoryArrayHelper::unwrapList($rows, self::TABLE) as $row) {
            $domainNo = (string) ($row['domain_no'] ?? '');
            $level = (string) ($row['security_level'] ?? 'normal');
            $note = (string) ($row['note'] ?? '');
            if ($domainNo !== '') {
                $result[$domainNo] = [
                    'level' => in_array($level, self::ALLOWED_LEVELS, true) ? $level : 'normal',
                    'note' => $note,
                ];
            }
        }

        return $result;
    }

    /**
     * Insert or update security level for a domain.
     *
     * @api Called from DomainSecurityLevelService
     * @return bool True on success
     */
    public function upsert(int $tenantId, string $domainNo, string $level, ?int $userId, ?string $note = null): bool
    {
        if ($domainNo === '' || !in_array($level, self::ALLOWED_LEVELS, true)) {
            return false;
        }

        $existing = $this->findByTenantAndDomainNo($tenantId, $domainNo);

        if ($existing !== null) {
            $result = DB::update(
                'UPDATE ' . self::TABLE . ' SET security_level = ?, note = ?, updated_by = ? WHERE tenant_id = ? AND domain_no = ?',
                $level,
                $note,
                $userId !== null ? (string) $userId : null,
                (string) $tenantId,
                $domainNo
            );

            return $result !== false;
        }

        $result = DB::insert(
            'INSERT INTO ' . self::TABLE . ' (tenant_id, domain_no, security_level, note, created_by, updated_by) VALUES (?, ?, ?, ?, ?, ?)',
            (string) $tenantId,
            $domainNo,
            $level,
            $note,
            $userId !== null ? (string) $userId : null,
            $userId !== null ? (string) $userId : null
        );

        return $result !== false;
    }

    /**
     * @api Reserved for future cleanup jobs
     */
    public function deleteByTenantAndDomainNo(int $tenantId, string $domainNo): bool
    {
        if ($domainNo === '') {
            return false;
        }

        $result = DB::update(
            'DELETE FROM ' . self::TABLE . ' WHERE tenant_id = ? AND domain_no = ?',
            (string) $tenantId,
            $domainNo
        );

        return $result !== false;
    }
}
