<?php
/**
 * Pure helper for computing PowerDNS RRset content-line sets.
 *
 * PowerDNS stores all records sharing a (name,type) as one RRset and rewrites
 * the whole set on REPLACE. To add/edit/delete a single logical record without
 * clobbering its siblings, compute the resulting content-line set here, then
 * submit it via PowerDNSIntegration::replaceRRset().
 *
 * @param array       $existing  Current content lines (e.g. ['10 mail1.x.', '20 mail2.x.'])
 * @param string      $op        'add' | 'edit' | 'delete'
 * @param string|null $target    Existing content line to edit/delete (null for add)
 * @param string|null $new       New content line for add/edit (null for delete)
 * @return array  New, reindexed, de-duplicated content-line set
 */
function dns_rrset_apply(array $existing, string $op, ?string $target, ?string $new): array {
    if (($op === 'add' || $op === 'edit') && $new === null) {
        throw new InvalidArgumentException("dns_rrset_apply: op '$op' requires a non-null new value");
    }
    $out = $existing;
    switch ($op) {
        case 'add':
            $out[] = $new;
            break;
        case 'edit':
            $found = false;
            foreach ($out as $i => $line) {
                if ($line === $target) { $out[$i] = $new; $found = true; break; }
            }
            if (!$found) { $out[] = $new; } // never silently drop the user's value
            break;
        case 'delete':
            $out = array_filter($out, fn($line) => $line !== $target);
            break;
        default:
            throw new InvalidArgumentException("dns_rrset_apply: unknown op '$op'");
    }
    // De-dupe preserving first-seen order, then reindex.
    $seen = [];
    $result = [];
    foreach ($out as $line) {
        if ($line === null || $line === '') { continue; }
        if (isset($seen[$line])) { continue; }
        $seen[$line] = true;
        $result[] = $line;
    }
    return $result;
}
