"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
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 __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
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 ScalewayCapabilitiesService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ScalewayCapabilitiesService = void 0;
const fs = __importStar(require("node:fs"));
const path = __importStar(require("node:path"));
const common_1 = require("@nestjs/common");
const cloud_provider_enum_1 = require("../../enums/cloud-provider.enum");
const credentials_entity_1 = require("../../../management/entities/credentials.entity");
const instances_1 = require("../../../../modules/providers/implementations/scaleway/generated/instances");
const iam_1 = require("../../../../modules/providers/implementations/scaleway/generated/iam");
const region_coordinates_1 = require("../../data/region-coordinates");
let ScalewayCapabilitiesService = ScalewayCapabilitiesService_1 = class ScalewayCapabilitiesService {
    constructor(credentialProvider) {
        this.credentialProvider = credentialProvider;
        this.logger = new common_1.Logger(ScalewayCapabilitiesService_1.name);
        this.baseUrl = 'https://api.scaleway.com';
    }
    async getAvailableRegions() {
        return this.getStaticRegions();
    }
    async getSupportedInstanceTypes() {
        this.logger.log('Fetching supported instance types from Scaleway API');
        try {
            const token = await this.credentialProvider.getActiveApiToken(cloud_provider_enum_1.CloudProvider.SCALEWAY);
            const api = new instances_1.InstanceTypesApi(new instances_1.Configuration({
                basePath: this.baseUrl,
                baseOptions: { headers: { 'X-Auth-Token': token } },
            }));
            const response = await api.listServersTypes(instances_1.ListServersTypesZoneEnum.FrPar1);
            const serversTypes = response.data.servers;
            return Object.entries(serversTypes ?? {})
                .filter(([, t]) => t.arch === 'x86_64')
                .map(([id, t]) => ({
                id,
                name: id,
                description: t.alt_name ?? id,
                cpu: t.ncpus ?? 0,
                memory: (t.ram ?? 0) / (1024 * 1024),
                disk: 0,
                bandwidth: t.network?.max_bandwidth ?? 0,
                pricing: {
                    hourly: t.hourly_price ?? 0,
                    monthly: typeof t.monthly_price === 'number' && t.monthly_price > 0
                        ? t.monthly_price
                        : (t.hourly_price ?? 0) * 730,
                    currency: 'EUR',
                },
                available: !t.end_of_service,
            }));
        }
        catch (error) {
            this.logger.error('Failed to fetch instance types from Scaleway API', error);
            this.logger.warn('Using fallback mock data for instance types');
            return this.getMockInstanceTypes();
        }
    }
    async getProviderInfo() {
        return {
            id: cloud_provider_enum_1.CloudProvider.SCALEWAY,
            name: 'scaleway',
            displayName: 'Scaleway',
            description: 'French cloud provider — Instances (VMs) and Elastic Metal (bare metal)',
            logoUrl: '/api/v1/management/providers/scaleway/logo',
            websiteUrl: 'https://www.scaleway.com',
            documentationUrl: 'https://www.scaleway.com/en/developers/',
            accessKeyDocumentationUrl: 'https://www.scaleway.com/en/docs/identity-and-access-management/iam/how-to/create-api-keys/',
            pricingUrl: 'https://www.scaleway.com/en/pricing/',
            supportUrl: 'https://console.scaleway.com/support',
            credentialFields: {
                type: credentials_entity_1.CredentialType.ACCESS_KEY_SECRET,
                supportsExpiry: true,
                fields: [
                    {
                        key: 'accessKey',
                        label: 'Access Key ID',
                        providerLabel: 'Access Key ID',
                        hint: 'Scaleway Console → IAM → API Keys → Access Key ID',
                        secret: false,
                        required: true,
                    },
                    {
                        key: 'secretKey',
                        label: 'Secret Key',
                        providerLabel: 'Secret Key',
                        hint: 'Scaleway Console → IAM → API Keys → Secret Key (shown once at creation)',
                        secret: true,
                        required: true,
                    },
                ],
            },
            dnsZoneDelegation: {
                nameservers: ['ns0.dom.scw.cloud', 'ns1.dom.scw.cloud'],
                delegationGuideUrl: 'https://www.scaleway.com/en/docs/network/domains-and-dns/how-to/add-external-domain/',
            },
        };
    }
    getLogo() {
        return fs.readFileSync(ScalewayCapabilitiesService_1.LOGO_PATH);
    }
    getLogoContentType() {
        return 'image/svg+xml';
    }
    async validateCredentials(credentials) {
        if (credentials.type !== credentials_entity_1.CredentialType.ACCESS_KEY_SECRET ||
            !credentials.secretKey) {
            return {
                success: false,
                message: 'An Access Key ID and Secret Key are required for Scaleway',
            };
        }
        try {
            // Validate by calling IAM listSSHKeys — lightweight, no side effects
            // BASE_PATH is already 'https://api.scaleway.com'; the client appends '/iam/v1alpha1/ssh-keys'
            const api = new iam_1.SSHKeysApi(new iam_1.Configuration({
                baseOptions: {
                    headers: { 'X-Auth-Token': credentials.secretKey },
                },
            }));
            await api.listSSHKeys();
            return { success: true, message: 'Credentials are valid' };
        }
        catch (error) {
            if (error.response?.status === 401 || error.response?.status === 403) {
                return { success: false, message: 'Invalid Secret Key' };
            }
            this.logger.error('Scaleway credential validation failed', error.message);
            return {
                success: false,
                message: 'Validation failed: ' + error.message,
            };
        }
    }
    getStaticCapabilities() {
        return {
            supportedInstanceTypes: [],
            supportedRegions: [],
            credentialType: 'api_key',
            features: {
                autoScaling: true, // Native Instance Scaling Groups with metrics-based policies
                loadBalancers: true,
                privateNetworking: true,
                snapshots: true,
                backups: true, // Block Storage backups + snapshot automation
                dnsZones: true,
                nodeProvisioning: true,
            },
            pricing: {
                currency: 'EUR',
                billingCycle: 'hourly',
                minimumCost: 0.0088, // DEV1-S: 2 vCPU, 2 GB RAM @ €0.0088/hr (practical minimum)
            },
            // Scaleway private networks are REGIONAL: each VNet is confined to a single region.
            // To connect servers across Paris, Amsterdam and Warsaw you need a VNet per region.
            // Subnets are flat within the region (no zone sub-scoping); routing is not supported.
            vnetTopology: {
                scope: 'regional',
                zones: [
                    {
                        id: 'fr-par',
                        displayName: 'Paris (France)',
                        coveredRegions: ['fr-par'],
                    },
                    {
                        id: 'nl-ams',
                        displayName: 'Amsterdam (Netherlands)',
                        coveredRegions: ['nl-ams'],
                    },
                    {
                        id: 'pl-waw',
                        displayName: 'Warsaw (Poland)',
                        coveredRegions: ['pl-waw'],
                    },
                ],
                supportsSubnets: false,
                subnetPerZone: false,
                supportsRoutes: false,
                // Scaleway VPC constraints (official docs: scaleway.com/en/docs/vpc/how-to/create-private-network/)
                // Both the private network and its subnets share the same /20–/28 prefix range.
                // Use 10.x.x.x ranges for consistency with other providers.
                vnetIpRange: { minPrefix: 20, maxPrefix: 28 },
                subnetIpRange: { minPrefix: 20, maxPrefix: 28 },
            },
        };
    }
    async getCapabilities() {
        const [regions, instanceTypes] = await Promise.all([
            this.getAvailableRegions(),
            this.getSupportedInstanceTypes(),
        ]);
        return {
            ...this.getStaticCapabilities(),
            supportedInstanceTypes: instanceTypes.map((t) => t.id),
            supportedRegions: regions,
        };
    }
    getStaticRegions() {
        const make = (id, name, country, flagEmoji) => {
            const coords = (0, region_coordinates_1.getRegionCoordinates)(cloud_provider_enum_1.CloudProvider.SCALEWAY, id);
            return {
                id,
                name,
                displayName: `${name}, ${country}`,
                location: country,
                available: true,
                flagEmoji,
                country,
                latitude: coords?.latitude,
                longitude: coords?.longitude,
            };
        };
        return [
            make('fr-par', 'Paris', 'France', '🇫🇷'),
            make('nl-ams', 'Amsterdam', 'Netherlands', '🇳🇱'),
            make('pl-waw', 'Warsaw', 'Poland', '🇵🇱'),
        ];
    }
    getMockInstanceTypes() {
        // Instances with ≥ 4 GB RAM suitable for observability workloads
        return [
            {
                id: 'DEV1-M',
                name: 'DEV1-M',
                description: 'Development 1 Medium — 3 vCPU, 4 GB RAM, 40 GB NVMe',
                cpu: 3,
                memory: 4096,
                disk: 40960,
                bandwidth: 200,
                pricing: { hourly: 0.0088, monthly: 6.42, currency: 'EUR' },
                available: true,
            },
            {
                id: 'DEV1-L',
                name: 'DEV1-L',
                description: 'Development 1 Large — 4 vCPU, 8 GB RAM, 80 GB NVMe',
                cpu: 4,
                memory: 8192,
                disk: 81920,
                bandwidth: 400,
                pricing: { hourly: 0.0175, monthly: 12.78, currency: 'EUR' },
                available: true,
            },
            {
                id: 'GP1-XS',
                name: 'GP1-XS',
                description: 'General Purpose XSmall — 4 vCPU, 16 GB RAM, local SSD',
                cpu: 4,
                memory: 16384,
                disk: 0,
                bandwidth: 500,
                pricing: { hourly: 0.0246, monthly: 17.99, currency: 'EUR' },
                available: true,
            },
            {
                id: 'GP1-S',
                name: 'GP1-S',
                description: 'General Purpose Small — 8 vCPU, 32 GB RAM, local SSD',
                cpu: 8,
                memory: 32768,
                disk: 0,
                bandwidth: 800,
                pricing: { hourly: 0.0493, monthly: 35.99, currency: 'EUR' },
                available: true,
            },
        ];
    }
};
exports.ScalewayCapabilitiesService = ScalewayCapabilitiesService;
ScalewayCapabilitiesService.LOGO_PATH = path.resolve(process.cwd(), 'dist/modules/providers/implementations/scaleway/assets/logo.svg');
exports.ScalewayCapabilitiesService = ScalewayCapabilitiesService = ScalewayCapabilitiesService_1 = __decorate([
    (0, common_1.Injectable)(),
    __param(0, (0, common_1.Inject)('ICredentialProvider')),
    __metadata("design:paramtypes", [Object])
], ScalewayCapabilitiesService);
