import { Controller, Get, Post, Delete, Body, Param, UseGuards, NotFoundException } from '@nestjs/common';
import { Roles, RolesGuard, TenantContextService } from '@it0/common';
import { CredentialRepository } from '../../../infrastructure/repositories/credential.repository';
import { CredentialVaultService } from '../../../infrastructure/crypto/credential-vault.service';
import { Credential } from '../../../domain/entities/credential.entity';
import * as crypto from 'crypto';

@Controller('api/v1/inventory/credentials')
export class CredentialController {
  constructor(
    private readonly credentialRepository: CredentialRepository,
    private readonly credentialVaultService: CredentialVaultService,
  ) {}

  @Get()
  async listCredentials() {
    const credentials = await this.credentialRepository.findAll();
    return credentials.map(c => this.toSafeOutput(c));
  }

  @Post()
  async createCredential(
    @Body() body: { name: string; type: string; plainValue: string; keyType?: string; expiresAt?: string },
  ) {
    const { encrypted, iv } = this.credentialVaultService.encrypt(body.plainValue);

    const credential = new Credential();
    credential.id = crypto.randomUUID();
    credential.tenantId = TenantContextService.getTenantId();
    credential.name = body.name;
    credential.type = body.type as Credential['type'];
    credential.encryptedValue = encrypted;
    credential.iv = iv;
    credential.keyType = body.keyType as Credential['keyType'];
    credential.expiresAt = body.expiresAt ? new Date(body.expiresAt) : undefined;
    credential.createdAt = new Date();

    const saved = await this.credentialRepository.save(credential);
    return this.toSafeOutput(saved);
  }

  @Get(':id')
  async getCredential(@Param('id') id: string) {
    const credential = await this.credentialRepository.findById(id);
    if (!credential) {
      throw new NotFoundException(`Credential ${id} not found`);
    }
    return this.toSafeOutput(credential);
  }

  @Delete(':id')
  async deleteCredential(@Param('id') id: string) {
    const credential = await this.credentialRepository.findById(id);
    if (!credential) {
      throw new NotFoundException(`Credential ${id} not found`);
    }
    await this.credentialRepository.remove(credential);
    return { message: 'Credential deleted', id };
  }

  @Post(':id/decrypt')
  @UseGuards(RolesGuard)
  @Roles('admin', 'platform_admin', 'platform_super_admin')
  async decryptCredential(@Param('id') id: string) {
    const credential = await this.credentialRepository.findById(id);
    if (!credential) {
      throw new NotFoundException(`Credential ${id} not found`);
    }
    const plainValue = this.credentialVaultService.decrypt(credential.encryptedValue, credential.iv);
    return { id: credential.id, name: credential.name, plainValue };
  }

  private toSafeOutput(credential: Credential) {
    return {
      id: credential.id,
      tenantId: credential.tenantId,
      name: credential.name,
      type: credential.type,
      fingerprint: credential.fingerprint,
      keyType: credential.keyType,
      createdBy: credential.createdBy,
      createdAt: credential.createdAt,
      expiresAt: credential.expiresAt,
      lastUsedAt: credential.lastUsedAt,
    };
  }
}
