"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 ProviderFirewallsController_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProviderFirewallsController = void 0;
const common_1 = require("@nestjs/common");
const swagger_1 = require("@nestjs/swagger");
const admin_guard_1 = require("../../auth/guards/admin.guard");
const admin_decorator_1 = require("../../auth/decorators/admin.decorator");
const firewall_provider_factory_1 = require("../services/firewall-provider.factory");
const provider_firewall_response_dto_1 = require("../dto/provider-firewall-response.dto");
const cloud_provider_enum_1 = require("../enums/cloud-provider.enum");
let ProviderFirewallsController = ProviderFirewallsController_1 = class ProviderFirewallsController {
    constructor(firewallProviderFactory) {
        this.firewallProviderFactory = firewallProviderFactory;
        this.logger = new common_1.Logger(ProviderFirewallsController_1.name);
    }
    /**
     * List all firewalls from the cloud provider
     * By default, filters for Flui-managed firewalls (managed-by=flui-cloud)
     */
    async listFirewalls(provider, labelSelector, name, clusterId, includeNonFlui) {
        // Validate provider
        const providerEnum = this.validateProvider(provider);
        // Get firewall provider service (throws if provider doesn't support firewalls)
        const firewallService = this.firewallProviderFactory.getFirewallProviderOrFail(providerEnum);
        // Build filters
        const filters = {};
        if (clusterId) {
            filters.clusterId = clusterId;
        }
        if (name) {
            filters.name = name;
        }
        // Apply default label selector if not explicitly disabled
        if (labelSelector) {
            filters.labelSelector = labelSelector;
        }
        else if (!includeNonFlui && !clusterId) {
            // Default: filter for Flui-managed firewalls
            filters.labelSelector = 'managed-by=flui-cloud';
        }
        this.logger.log(`Listing firewalls from provider ${provider} with filters: ${JSON.stringify(filters)}`);
        // Get firewalls from provider
        const firewalls = await firewallService.listFirewalls(filters);
        // Map to response DTOs
        return firewalls.map((firewall) => this.mapToResponseDto(firewall));
    }
    /**
     * Get details of a specific firewall from the cloud provider
     */
    async getFirewall(provider, firewallId) {
        // Validate provider
        const providerEnum = this.validateProvider(provider);
        // Get firewall provider service (throws if provider doesn't support firewalls)
        const firewallService = this.firewallProviderFactory.getFirewallProviderOrFail(providerEnum);
        this.logger.log(`Getting firewall ${firewallId} from provider ${provider}`);
        // Get firewall from provider
        const firewall = await firewallService.getFirewall(firewallId);
        if (!firewall) {
            throw new common_1.NotFoundException(`Firewall with ID ${firewallId} not found on provider ${provider}`);
        }
        // Map to response DTO
        return this.mapToResponseDto(firewall);
    }
    /**
     * Delete firewall from cloud provider (direct provider deletion, no database interaction)
     */
    async deleteFirewall(provider, firewallId, confirm) {
        // Safety check - require explicit confirmation
        if (confirm !== true) {
            throw new common_1.BadRequestException('Must provide confirm=true query parameter to delete firewall from provider');
        }
        // Validate provider
        const providerEnum = this.validateProvider(provider);
        // Get firewall provider service (throws if provider doesn't support firewalls)
        const firewallService = this.firewallProviderFactory.getFirewallProviderOrFail(providerEnum);
        this.logger.log(`Deleting firewall ${firewallId} from provider ${provider}`);
        try {
            // Delete from provider (no database interaction)
            await firewallService.deleteFirewall(firewallId);
            this.logger.log(`Firewall ${firewallId} deleted successfully from provider ${provider}`);
        }
        catch (error) {
            this.logger.error(`Failed to delete firewall ${firewallId} from provider ${provider}: ${error.message}`);
            throw error;
        }
    }
    /**
     * Validate provider parameter and convert to enum
     */
    validateProvider(provider) {
        const lowerProvider = provider.toLowerCase();
        if (!Object.values(cloud_provider_enum_1.CloudProvider).includes(lowerProvider)) {
            throw new common_1.BadRequestException(`Invalid provider: ${provider}. Must be one of: ${Object.values(cloud_provider_enum_1.CloudProvider).join(', ')}`);
        }
        return lowerProvider;
    }
    /**
     * Map FirewallDetails to ProviderFirewallResponseDto
     */
    mapToResponseDto(firewall) {
        return {
            id: firewall.id,
            name: firewall.name,
            rules: firewall.rules.map((rule) => ({
                description: rule.description,
                direction: rule.direction,
                protocol: rule.protocol,
                port: rule.port,
                sourceIps: rule.sourceIps,
                destinationIps: rule.destinationIps,
            })),
            labels: firewall.labels,
            appliedServers: firewall.appliedTo.map((server) => ({
                serverId: server.serverId,
                serverName: server.serverName,
            })),
        };
    }
};
exports.ProviderFirewallsController = ProviderFirewallsController;
__decorate([
    (0, common_1.Get)(),
    (0, swagger_1.ApiOperation)({
        summary: 'List firewalls from cloud provider',
        description: 'Retrieves all firewalls from the specified cloud provider. By default, filters for Flui-managed firewalls using the "managed-by=flui-cloud" label selector. Returns firewall details including applied servers.',
    }),
    (0, swagger_1.ApiParam)({
        name: 'provider',
        enum: cloud_provider_enum_1.CloudProvider,
        description: 'Cloud provider (HETZNER or CONTABO)',
        example: 'HETZNER',
    }),
    (0, swagger_1.ApiQuery)({
        name: 'labelSelector',
        required: false,
        description: 'Label selector for filtering firewalls. Default: "managed-by=flui-cloud". Use comma-separated key=value pairs for multiple labels.',
        example: 'managed-by=flui-cloud,flui-cluster-id=abc-123',
    }),
    (0, swagger_1.ApiQuery)({
        name: 'name',
        required: false,
        description: 'Filter firewalls by name (exact match)',
        example: 'flui-my-cluster-system-webapp',
    }),
    (0, swagger_1.ApiQuery)({
        name: 'clusterId',
        required: false,
        description: 'Filter firewalls by cluster ID (shorthand for labelSelector=flui-cluster-id=<clusterId>)',
        example: 'abc-123-def-456',
    }),
    (0, swagger_1.ApiQuery)({
        name: 'includeNonFlui',
        required: false,
        type: Boolean,
        description: 'Include non-Flui-managed firewalls. When true, disables default "managed-by=flui-cloud" filter.',
        example: false,
    }),
    (0, swagger_1.ApiResponse)({
        status: 200,
        description: 'List of firewalls from the provider',
        type: [provider_firewall_response_dto_1.ProviderFirewallResponseDto],
    }),
    (0, swagger_1.ApiResponse)({
        status: 400,
        description: 'Invalid provider specified',
    }),
    __param(0, (0, common_1.Param)('provider')),
    __param(1, (0, common_1.Query)('labelSelector')),
    __param(2, (0, common_1.Query)('name')),
    __param(3, (0, common_1.Query)('clusterId')),
    __param(4, (0, common_1.Query)('includeNonFlui')),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String, String, String, Boolean]),
    __metadata("design:returntype", Promise)
], ProviderFirewallsController.prototype, "listFirewalls", null);
__decorate([
    (0, common_1.Get)(':id'),
    (0, swagger_1.ApiOperation)({
        summary: 'Get firewall details from cloud provider',
        description: 'Retrieves detailed information about a specific firewall from the cloud provider, including rules, labels, and applied servers.',
    }),
    (0, swagger_1.ApiParam)({
        name: 'provider',
        enum: cloud_provider_enum_1.CloudProvider,
        description: 'Cloud provider (HETZNER or CONTABO)',
        example: 'HETZNER',
    }),
    (0, swagger_1.ApiParam)({
        name: 'id',
        description: 'Provider firewall ID',
        example: '12345678',
    }),
    (0, swagger_1.ApiResponse)({
        status: 200,
        description: 'Firewall details',
        type: provider_firewall_response_dto_1.ProviderFirewallResponseDto,
    }),
    (0, swagger_1.ApiResponse)({
        status: 404,
        description: 'Firewall not found',
    }),
    (0, swagger_1.ApiResponse)({
        status: 400,
        description: 'Invalid provider specified',
    }),
    __param(0, (0, common_1.Param)('provider')),
    __param(1, (0, common_1.Param)('id')),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String]),
    __metadata("design:returntype", Promise)
], ProviderFirewallsController.prototype, "getFirewall", null);
__decorate([
    (0, common_1.Delete)(':id'),
    (0, common_1.UseGuards)(admin_guard_1.AdminGuard),
    (0, admin_decorator_1.Admin)(),
    (0, common_1.HttpCode)(common_1.HttpStatus.NO_CONTENT),
    (0, swagger_1.ApiOperation)({
        summary: 'Delete firewall from cloud provider',
        description: 'Deletes a firewall directly from the cloud provider without any database interaction. ' +
            'Use with caution - this is a direct provider operation. Requires confirm=true query parameter.',
    }),
    (0, swagger_1.ApiParam)({
        name: 'provider',
        enum: cloud_provider_enum_1.CloudProvider,
        description: 'Cloud provider (HETZNER or CONTABO)',
        example: 'HETZNER',
    }),
    (0, swagger_1.ApiParam)({
        name: 'id',
        description: 'Provider firewall ID',
        example: '12345678',
    }),
    (0, swagger_1.ApiQuery)({
        name: 'confirm',
        required: true,
        type: Boolean,
        description: 'Confirmation required to delete firewall (must be true). Safety mechanism to prevent accidental deletion.',
        example: true,
    }),
    (0, swagger_1.ApiResponse)({
        status: 204,
        description: 'Firewall deleted successfully',
    }),
    (0, swagger_1.ApiResponse)({
        status: 400,
        description: 'Invalid provider or confirmation not provided',
    }),
    (0, swagger_1.ApiResponse)({
        status: 404,
        description: 'Firewall not found on provider',
    }),
    __param(0, (0, common_1.Param)('provider')),
    __param(1, (0, common_1.Param)('id')),
    __param(2, (0, common_1.Query)('confirm')),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String, Boolean]),
    __metadata("design:returntype", Promise)
], ProviderFirewallsController.prototype, "deleteFirewall", null);
exports.ProviderFirewallsController = ProviderFirewallsController = ProviderFirewallsController_1 = __decorate([
    (0, swagger_1.ApiTags)('Provider Firewalls'),
    (0, swagger_1.ApiBearerAuth)(),
    (0, common_1.Controller)('providers/:provider/firewalls'),
    __metadata("design:paramtypes", [firewall_provider_factory_1.FirewallProviderFactory])
], ProviderFirewallsController);
