import {
  Controller,
  Post,
  Body,
  UseGuards,
  HttpCode,
  HttpStatus,
  Req,
  Logger,
} from '@nestjs/common';
import { BackupShareApplicationService } from '../../application/services/backup-share-application.service';
import { StoreBackupShareCommand } from '../../application/commands/store-backup-share/store-backup-share.command';
import { RevokeShareCommand } from '../../application/commands/revoke-share/revoke-share.command';
import { GetBackupShareQuery } from '../../application/queries/get-backup-share/get-backup-share.query';
import { ServiceAuthGuard } from '../../shared/guards/service-auth.guard';
import { StoreShareDto } from '../dto/request/store-share.dto';
import { RetrieveShareDto } from '../dto/request/retrieve-share.dto';
import { RevokeShareDto } from '../dto/request/revoke-share.dto';
import {
  StoreShareResponseDto,
  RetrieveShareResponseDto,
  RevokeShareResponseDto,
} from '../dto/response/share-info.dto';

@Controller('backup-share')
@UseGuards(ServiceAuthGuard)
export class BackupShareController {
  private readonly logger = new Logger(BackupShareController.name);

  constructor(
    private readonly backupShareService: BackupShareApplicationService,
  ) {}

  @Post('store')
  @HttpCode(HttpStatus.CREATED)
  async storeShare(
    @Body() dto: StoreShareDto,
    @Req() request: any,
  ): Promise<StoreShareResponseDto> {
    this.logger.log(`[STORE] Received store request: userId=${dto.userId}, accountSequence=${dto.accountSequence}, publicKey=${dto.publicKey?.substring(0, 20)}...`);

    try {
      const command = new StoreBackupShareCommand(
        dto.userId,
        dto.accountSequence,
        dto.publicKey,
        dto.encryptedShareData,
        request.sourceService,
        request.sourceIp,
        dto.threshold,
        dto.totalParties,
      );

      const result = await this.backupShareService.storeBackupShare(command);

      this.logger.log(`[STORE] SUCCESS: shareId=${result.shareId}, userId=${dto.userId}, accountSequence=${dto.accountSequence}`);

      return {
        success: true,
        shareId: result.shareId,
        message: 'Backup share stored successfully',
      };
    } catch (error) {
      this.logger.error(`[STORE] FAILED: userId=${dto.userId}, accountSequence=${dto.accountSequence}, error=${error.message}`);
      throw error;
    }
  }

  @Post('retrieve')
  @HttpCode(HttpStatus.OK)
  async retrieveShare(
    @Body() dto: RetrieveShareDto,
    @Req() request: any,
  ): Promise<RetrieveShareResponseDto> {
    const query = new GetBackupShareQuery(
      dto.userId,
      dto.publicKey,
      dto.recoveryToken,
      request.sourceService,
      request.sourceIp,
      dto.deviceId,
    );

    const result = await this.backupShareService.getBackupShare(query);

    return {
      success: true,
      encryptedShareData: result.encryptedShareData,
      partyIndex: result.partyIndex,
      publicKey: result.publicKey,
    };
  }

  @Post('revoke')
  @HttpCode(HttpStatus.OK)
  async revokeShare(
    @Body() dto: RevokeShareDto,
    @Req() request: any,
  ): Promise<RevokeShareResponseDto> {
    const command = new RevokeShareCommand(
      dto.userId,
      dto.publicKey,
      dto.reason,
      request.sourceService,
      request.sourceIp,
    );

    await this.backupShareService.revokeShare(command);

    return {
      success: true,
      message: 'Backup share revoked successfully',
    };
  }
}
