"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
var ScalewayDnsService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ScalewayDnsService = void 0;
const common_1 = require("@nestjs/common");
const domain_1 = require("./generated/domain");
const dns_provider_interface_1 = require("../../interfaces/dns-provider.interface");
const cloud_provider_enum_1 = require("../../enums/cloud-provider.enum");
let ScalewayDnsService = ScalewayDnsService_1 = class ScalewayDnsService {
    constructor(credentialProvider) {
        this.credentialProvider = credentialProvider;
        this.logger = new common_1.Logger(ScalewayDnsService_1.name);
    }
    // ─── API factory ────────────────────────────────────────────────────────────
    async createZonesApi() {
        const token = await this.credentialProvider.getActiveApiToken(cloud_provider_enum_1.CloudProvider.SCALEWAY);
        return new domain_1.DNSZonesApi(new domain_1.Configuration({
            baseOptions: { headers: { 'X-Auth-Token': token } },
        }));
    }
    async createRecordsApi() {
        const token = await this.credentialProvider.getActiveApiToken(cloud_provider_enum_1.CloudProvider.SCALEWAY);
        return new domain_1.RecordsApi(new domain_1.Configuration({
            baseOptions: { headers: { 'X-Auth-Token': token } },
        }));
    }
    // ─── Zone operations ────────────────────────────────────────────────────────
    async listZones() {
        const api = await this.createZonesApi();
        const resp = await api.listDNSZones('', '');
        return (resp.data.dns_zones ?? []).map((z) => this.mapZone(z));
    }
    async getZone(zoneId) {
        const zones = await this.listZones();
        return zones.find((z) => z.zoneId === zoneId) ?? null;
    }
    async getZoneByName(name) {
        return this.getZone(name);
    }
    // ─── Record operations ──────────────────────────────────────────────────────
    async listRecords(zoneId) {
        const api = await this.createRecordsApi();
        const resp = await api.listDNSZoneRecords(zoneId, '');
        return (resp.data.records ?? []).map((r) => this.mapRecord(r, zoneId));
    }
    async getRecord(zoneId, recordId) {
        const api = await this.createRecordsApi();
        const resp = await api.listDNSZoneRecords(zoneId, '', undefined, undefined, undefined, undefined, undefined, recordId);
        const r = resp.data.records?.[0];
        return r ? this.mapRecord(r, zoneId) : null;
    }
    async createRecord(config) {
        const api = await this.createRecordsApi();
        await api.updateDNSZoneRecords(config.zoneId, {
            changes: [
                {
                    add: {
                        records: [
                            {
                                name: config.name,
                                type: config.type,
                                data: config.value,
                                ttl: config.ttl ?? 300,
                            },
                        ],
                    },
                },
            ],
            return_all_records: false,
        });
        // Retrieve the newly created record by name+type
        const listResp = await api.listDNSZoneRecords(config.zoneId, config.name, undefined, undefined, undefined, undefined, config.type);
        const created = (listResp.data.records ?? []).find((r) => r.data === config.value);
        if (!created) {
            throw new Error(`Record created but could not be retrieved (zone=${config.zoneId} name=${config.name} type=${config.type})`);
        }
        return this.mapRecord(created, config.zoneId);
    }
    async updateRecord(config) {
        const api = await this.createRecordsApi();
        // Scaleway has no direct update — use set by id
        await api.updateDNSZoneRecords(config.zoneId, {
            changes: [
                {
                    set: {
                        id: config.recordId,
                        records: [
                            {
                                name: config.name,
                                type: config.type,
                                data: config.value,
                                ttl: config.ttl ?? 300,
                            },
                        ],
                    },
                },
            ],
            return_all_records: false,
        });
        const updated = await this.getRecord(config.zoneId, config.recordId);
        if (!updated) {
            throw new Error(`Record updated but could not be retrieved (zoneId=${config.zoneId} recordId=${config.recordId})`);
        }
        return updated;
    }
    async deleteRecord(zoneId, recordId) {
        const api = await this.createRecordsApi();
        await api.updateDNSZoneRecords(zoneId, {
            changes: [
                {
                    delete: { id: recordId },
                },
            ],
        });
    }
    async bulkCreateRecords(zoneId, records) {
        const api = await this.createRecordsApi();
        await api.updateDNSZoneRecords(zoneId, {
            changes: records.map((r) => ({
                add: {
                    records: [
                        {
                            name: r.name,
                            type: r.type,
                            data: r.value,
                            ttl: r.ttl ?? 300,
                        },
                    ],
                },
            })),
            return_all_records: false,
        });
        // Return all records for the zone after bulk insert
        const allRecords = await this.listRecords(zoneId);
        return allRecords.filter((existing) => records.some((r) => existing.name === r.name &&
            existing.type === r.type &&
            existing.value === r.value));
    }
    async testConnection() {
        try {
            await this.listZones();
            return { success: true };
        }
        catch (e) {
            return { success: false, error: e.message };
        }
    }
    // ─── Mapping helpers ─────────────────────────────────────────────────────────
    mapZone(z) {
        // Scaleway zone name = subdomain + domain (e.g. 'example.com' or 'sub.example.com')
        const name = z.subdomain ? `${z.subdomain}.${z.domain}` : (z.domain ?? '');
        return {
            zoneId: name,
            name,
            ttl: 300,
            recordCount: 0,
            status: z.status ?? 'active',
        };
    }
    mapRecord(r, zoneId) {
        // Scaleway records have no label support — deleteRecordsByClusterId is a no-op for Scaleway zones
        return {
            recordId: r.id ?? '',
            zoneId,
            type: r.type ?? dns_provider_interface_1.DnsRecordType.A,
            name: r.name ?? '',
            value: r.data ?? '',
            ttl: r.ttl ?? 300,
        };
    }
};
exports.ScalewayDnsService = ScalewayDnsService;
exports.ScalewayDnsService = ScalewayDnsService = ScalewayDnsService_1 = __decorate([
    (0, common_1.Injectable)(),
    __param(0, (0, common_1.Inject)('ICredentialProvider')),
    __metadata("design:paramtypes", [Object])
], ScalewayDnsService);
