import { Body, Controller, Get, Param, Patch, Post, Put, Query, Res } from '@nestjs/common';
import { Response } from 'express';
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
import {
  CreatePlanSchema, UpdatePlanSchema, ProvisionTenantSchema, UpdateTenantSchema, UpdateSubscriptionSchema, SetFeatureFlagSchema, UsageQuerySchema,
  CreatePlanDto, ProvisionTenantDto, UpdateTenantDto,
} from '@wms/shared';
import { z } from 'zod';
import { PlatformOnly } from '@/common/auth/decorators';
import { zodBody, zodQuery } from '@/common/validation/zod.pipe';
import { PlatformService } from './platform.service';
import { TenantProvisioningService } from './tenant-provisioning.service';
import { TenantExportService } from './tenant-export.service';

/** SaaS operator console. Only platform staff tokens are accepted. */
@ApiTags('platform')
@ApiBearerAuth()
@PlatformOnly()
@Controller('platform')
export class PlatformController {
  constructor(
    private readonly platform: PlatformService,
    private readonly provisioning: TenantProvisioningService,
    private readonly exporter: TenantExportService,
  ) {}

  /** Full data export of one tenant as a zip of NDJSON files (contract exit, migration, audit). */
  @Get('tenants/:id/export')
  async exportTenant(@Param('id') id: string, @Res() res: Response) {
    const { stream, fileName } = await this.exporter.exportTenant(id);
    res.setHeader('Content-Type', 'application/zip');
    res.setHeader('Content-Disposition', `attachment; filename="${fileName}"`);
    stream.pipe(res);
  }

  @Get('plans')
  listPlans() {
    return this.platform.listPlans();
  }

  @Post('plans')
  createPlan(@Body(zodBody(CreatePlanSchema)) dto: CreatePlanDto) {
    return this.platform.createPlan(dto);
  }

  @Patch('plans/:id')
  updatePlan(@Param('id') id: string, @Body(zodBody(UpdatePlanSchema)) dto: z.infer<typeof UpdatePlanSchema>) {
    return this.platform.updatePlan(id, dto);
  }

  @Get('tenants')
  listTenants() {
    return this.platform.listTenants();
  }

  @Post('tenants')
  provision(@Body(zodBody(ProvisionTenantSchema)) dto: ProvisionTenantDto) {
    return this.provisioning.provision(dto);
  }

  @Get('tenants/:id')
  getTenant(@Param('id') id: string) {
    return this.platform.getTenant(id);
  }

  @Patch('tenants/:id')
  updateTenant(@Param('id') id: string, @Body(zodBody(UpdateTenantSchema)) dto: UpdateTenantDto) {
    return this.platform.updateTenant(id, dto);
  }

  @Patch('tenants/:id/subscription')
  updateSubscription(@Param('id') id: string, @Body(zodBody(UpdateSubscriptionSchema)) dto: z.infer<typeof UpdateSubscriptionSchema>) {
    return this.platform.updateSubscription(id, dto);
  }

  @Put('tenants/:id/features')
  setFeature(@Param('id') id: string, @Body(zodBody(SetFeatureFlagSchema)) dto: z.infer<typeof SetFeatureFlagSchema>) {
    return this.platform.setFeatureFlag(id, dto);
  }

  @Get('usage')
  usage(@Query(zodQuery(UsageQuerySchema)) q: z.infer<typeof UsageQuerySchema>) {
    return this.platform.usage(q);
  }
}
