import {
  Controller,
  Get,
  Post,
  Body,
  Param,
  Query,
  HttpCode,
  HttpStatus,
} from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiQuery } from '@nestjs/swagger';
import { IsString, IsOptional, IsNumber, Matches } from 'class-validator';
import { MarketMakerService, LedgerType, AssetType } from '../../application/services/market-maker.service';
import { BlockchainClient } from '../../infrastructure/blockchain/blockchain.client';
import { Public } from '../../shared/guards/jwt-auth.guard';

// DTO 定义
class InitializeMarketMakerDto {
  @IsOptional()
  @IsString()
  name?: string;

  @IsString()
  accountSequence: string;

  @IsOptional()
  @IsString()
  initialCash?: string;

  @IsOptional()
  @IsNumber()
  maxBuyRatio?: number;

  @IsOptional()
  @IsNumber()
  minIntervalMs?: number;

  @IsOptional()
  @IsNumber()
  maxIntervalMs?: number;
}

class DepositDto {
  @IsString()
  amount: string;

  @IsOptional()
  @IsString()
  memo?: string;
}

class WithdrawDto {
  @IsString()
  amount: string;

  @IsOptional()
  @IsString()
  memo?: string;
}

class UpdateConfigDto {
  @IsOptional()
  @IsNumber()
  maxBuyRatio?: number;

  @IsOptional()
  @IsNumber()
  minIntervalMs?: number;

  @IsOptional()
  @IsNumber()
  maxIntervalMs?: number;

  @IsOptional()
  @IsString()
  priceStrategy?: string;

  @IsOptional()
  @IsNumber()
  discountRate?: number;

  @IsOptional()
  @IsString()
  kavaWalletAddress?: string;

  @IsOptional()
  @IsString()
  eusdtWalletAddress?: string;
}

class UpdateMakerConfigDto {
  @IsOptional()
  bidEnabled?: boolean;

  @IsOptional()
  @IsNumber()
  bidLevels?: number;

  @IsOptional()
  @IsNumber()
  bidSpread?: number;

  @IsOptional()
  @IsNumber()
  bidLevelSpacing?: number;

  @IsOptional()
  @IsString()
  bidQuantityPerLevel?: string;

  @IsOptional()
  askEnabled?: boolean;

  @IsOptional()
  @IsNumber()
  askLevels?: number;

  @IsOptional()
  @IsNumber()
  askSpread?: number;

  @IsOptional()
  @IsNumber()
  askLevelSpacing?: number;

  @IsOptional()
  @IsString()
  askQuantityPerLevel?: string;

  @IsOptional()
  @IsNumber()
  refreshIntervalMs?: number;
}

// 区块链提现 DTO
class BlockchainWithdrawDto {
  @IsString()
  @Matches(/^0x[a-fA-F0-9]{40}$/, { message: 'Invalid EVM address format' })
  toAddress: string;

  @IsString()
  amount: string;
}

@ApiTags('Market Maker')
@Controller('admin/market-maker')
export class MarketMakerController {
  constructor(
    private readonly marketMakerService: MarketMakerService,
    private readonly blockchainClient: BlockchainClient,
  ) {}

  @Post('initialize')
  @Public() // TODO: 生产环境应添加管理员权限验证
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '初始化做市商' })
  @ApiResponse({ status: 200, description: '做市商初始化成功' })
  async initialize(@Body() dto: InitializeMarketMakerDto) {
    const config = await this.marketMakerService.initializeConfig({
      name: dto.name,
      accountSequence: dto.accountSequence,
      initialCash: dto.initialCash,
      maxBuyRatio: dto.maxBuyRatio,
      minIntervalMs: dto.minIntervalMs,
      maxIntervalMs: dto.maxIntervalMs,
    });

    return {
      success: true,
      message: '做市商初始化成功',
      config: {
        id: config.id,
        name: config.name,
        accountSequence: config.accountSequence,
        cashBalance: config.cashBalance.toString(),
        shareBalance: config.shareBalance.toString(),
        maxBuyRatio: config.maxBuyRatio.toString(),
        minIntervalMs: config.minIntervalMs,
        maxIntervalMs: config.maxIntervalMs,
        isActive: config.isActive,
      },
    };
  }

  @Get(':name/config')
  @Public()
  @ApiOperation({ summary: '获取做市商配置' })
  @ApiResponse({ status: 200, description: '返回做市商配置' })
  async getConfig(@Param('name') name: string) {
    const config = await this.marketMakerService.getConfig(name);
    const runningStatus = this.marketMakerService.getRunningStatus();

    if (!config) {
      return {
        success: false,
        message: `做市商 ${name} 不存在`,
        config: null,
        runningStatus,
      };
    }

    return {
      success: true,
      config: {
        id: config.id,
        name: config.name,
        accountSequence: config.accountSequence,
        cashBalance: config.cashBalance.toString(),
        shareBalance: config.shareBalance.toString(),
        frozenCash: config.frozenCash.toString(),
        frozenShares: config.frozenShares.toString(),
        availableCash: config.cashBalance.minus(config.frozenCash).toString(),
        availableShares: config.shareBalance.minus(config.frozenShares).toString(),
        maxBuyRatio: config.maxBuyRatio.toString(),
        minIntervalMs: config.minIntervalMs,
        maxIntervalMs: config.maxIntervalMs,
        priceStrategy: config.priceStrategy,
        discountRate: config.discountRate.toString(),
        isActive: config.isActive,
        kavaWalletAddress: config.kavaWalletAddress,
        eusdtWalletAddress: config.eusdtWalletAddress,
      },
      runningStatus,
    };
  }

  @Get('status')
  @Public()
  @ApiOperation({ summary: '获取做市商运行状态' })
  @ApiResponse({ status: 200, description: '返回运行状态' })
  getRunningStatus() {
    const status = this.marketMakerService.getRunningStatus();
    return {
      success: true,
      ...status,
      modeDescription: {
        idle: '空闲（未运行）',
        taker: '吃单模式（自动买入用户卖单）',
        maker: '挂单模式（双边深度做市）',
      }[status.mode],
    };
  }

  @Post(':name/config')
  @Public()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '更新做市商配置' })
  @ApiResponse({ status: 200, description: '配置更新成功' })
  async updateConfig(@Param('name') name: string, @Body() dto: UpdateConfigDto) {
    const config = await this.marketMakerService.updateConfig(name, dto);
    if (!config) {
      return {
        success: false,
        message: `做市商 ${name} 不存在`,
      };
    }

    return {
      success: true,
      message: '配置更新成功',
      config: {
        maxBuyRatio: config.maxBuyRatio.toString(),
        minIntervalMs: config.minIntervalMs,
        maxIntervalMs: config.maxIntervalMs,
        priceStrategy: config.priceStrategy,
        discountRate: config.discountRate.toString(),
      },
    };
  }

  @Post(':name/deposit')
  @Public()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '充值资金到做市商账户' })
  @ApiResponse({ status: 200, description: '充值成功' })
  async deposit(@Param('name') name: string, @Body() dto: DepositDto) {
    await this.marketMakerService.deposit(name, dto.amount, dto.memo);
    const config = await this.marketMakerService.getConfig(name);

    return {
      success: true,
      message: `充值成功: ${dto.amount}`,
      newBalance: config?.cashBalance.toString(),
    };
  }

  @Post(':name/withdraw')
  @Public()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '从做市商账户提现' })
  @ApiResponse({ status: 200, description: '提现成功' })
  async withdraw(@Param('name') name: string, @Body() dto: WithdrawDto) {
    await this.marketMakerService.withdraw(name, dto.amount, dto.memo);
    const config = await this.marketMakerService.getConfig(name);

    return {
      success: true,
      message: `提现成功: ${dto.amount}`,
      newBalance: config?.cashBalance.toString(),
    };
  }

  @Post(':name/deposit-shares')
  @Public()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '充值积分股到做市商账户' })
  @ApiResponse({ status: 200, description: '积分股充值成功' })
  async depositShares(@Param('name') name: string, @Body() dto: DepositDto) {
    await this.marketMakerService.depositShares(name, dto.amount, dto.memo);
    const config = await this.marketMakerService.getConfig(name);

    return {
      success: true,
      message: `积分股充值成功: ${dto.amount}`,
      newShareBalance: config?.shareBalance.toString(),
    };
  }

  @Post(':name/withdraw-shares')
  @Public()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '从做市商账户提取积分股' })
  @ApiResponse({ status: 200, description: '积分股提取成功' })
  async withdrawShares(@Param('name') name: string, @Body() dto: WithdrawDto) {
    await this.marketMakerService.withdrawShares(name, dto.amount, dto.memo);
    const config = await this.marketMakerService.getConfig(name);

    return {
      success: true,
      message: `积分股提取成功: ${dto.amount}`,
      newShareBalance: config?.shareBalance.toString(),
    };
  }

  // ============ 区块链提现接口 ============

  @Post(':name/blockchain-withdraw-cash')
  @Public()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '区块链提现积分值（fUSDT）' })
  @ApiResponse({ status: 200, description: '区块链提现结果' })
  async blockchainWithdrawCash(@Param('name') name: string, @Body() dto: BlockchainWithdrawDto) {
    // 1. 先从做市商账户扣款
    await this.marketMakerService.withdraw(name, dto.amount, `区块链提现到 ${dto.toAddress.slice(0, 10)}...`);

    // 2. 调用区块链服务执行转账
    const result = await this.blockchainClient.transferFusdt(dto.toAddress, dto.amount);

    if (!result.success) {
      // 如果链上转账失败，需要回滚（充值回去）
      await this.marketMakerService.deposit(name, dto.amount, `区块链提现失败回滚: ${result.error}`);
      return {
        success: false,
        error: result.error,
        message: '区块链转账失败，已回滚',
      };
    }

    const config = await this.marketMakerService.getConfig(name);
    return {
      success: true,
      message: `区块链提现成功: ${dto.amount} fUSDT`,
      txHash: result.txHash,
      blockNumber: result.blockNumber,
      newBalance: config?.cashBalance.toString(),
    };
  }

  @Post(':name/blockchain-withdraw-shares')
  @Public()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '区块链提现积分股（eUSDT）' })
  @ApiResponse({ status: 200, description: '区块链提现结果' })
  async blockchainWithdrawShares(@Param('name') name: string, @Body() dto: BlockchainWithdrawDto) {
    // 1. 先从做市商账户扣款
    await this.marketMakerService.withdrawShares(name, dto.amount, `区块链提现到 ${dto.toAddress.slice(0, 10)}...`);

    // 2. 调用区块链服务执行转账
    const result = await this.blockchainClient.transferEusdt(dto.toAddress, dto.amount);

    if (!result.success) {
      // 如果链上转账失败，需要回滚（充值回去）
      await this.marketMakerService.depositShares(name, dto.amount, `区块链提现失败回滚: ${result.error}`);
      return {
        success: false,
        error: result.error,
        message: '区块链转账失败，已回滚',
      };
    }

    const config = await this.marketMakerService.getConfig(name);
    return {
      success: true,
      message: `区块链提现成功: ${dto.amount} eUSDT`,
      txHash: result.txHash,
      blockNumber: result.blockNumber,
      newBalance: config?.shareBalance.toString(),
    };
  }

  @Post(':name/start')
  @Public()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '启动做市商' })
  @ApiResponse({ status: 200, description: '做市商已启动' })
  async start(@Param('name') name: string) {
    await this.marketMakerService.start(name);

    return {
      success: true,
      message: `做市商 ${name} 已启动`,
    };
  }

  @Post(':name/stop')
  @Public()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '停止做市商' })
  @ApiResponse({ status: 200, description: '做市商已停止' })
  async stop(@Param('name') name: string) {
    await this.marketMakerService.stop(name);

    return {
      success: true,
      message: `做市商 ${name} 已停止`,
    };
  }

  @Post(':name/take-order')
  @Public()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '手动执行一次吃单' })
  @ApiResponse({ status: 200, description: '吃单执行结果' })
  async takeOrder(@Param('name') name: string) {
    const result = await this.marketMakerService.executeTakeOrder(name);
    return result;
  }

  @Get(':name/stats')
  @Public()
  @ApiOperation({ summary: '获取做市商统计信息' })
  @ApiResponse({ status: 200, description: '返回做市商统计' })
  async getStats(@Param('name') name: string) {
    const stats = await this.marketMakerService.getStats(name);

    if (!stats.config) {
      return {
        success: false,
        message: `做市商 ${name} 不存在`,
      };
    }

    return {
      success: true,
      config: {
        name: stats.config.name,
        cashBalance: stats.config.cashBalance.toString(),
        shareBalance: stats.config.shareBalance.toString(),
        isActive: stats.config.isActive,
      },
      recentTrades: stats.recentTrades.map((t) => ({
        type: t.type,
        assetType: t.assetType,
        amount: t.amount.toString(),
        price: t.price?.toString(),
        quantity: t.quantity?.toString(),
        counterpartySeq: t.counterpartySeq,
        orderNo: t.orderNo,
        memo: t.memo,
        createdAt: t.createdAt,
      })),
      dailyStats: stats.dailyStats.map((s) => ({
        date: s.date,
        buyCount: s.buyCount,
        buyQuantity: s.buyQuantity.toString(),
        buyAmount: s.buyAmount.toString(),
        avgBuyPrice: s.avgBuyPrice.toString(),
        sellCount: s.sellCount,
        sellQuantity: s.sellQuantity.toString(),
        sellAmount: s.sellAmount.toString(),
        realizedPnl: s.realizedPnl.toString(),
      })),
    };
  }

  @Get(':name/ledgers')
  @Public()
  @ApiOperation({ summary: '获取做市商分类账流水' })
  @ApiQuery({ name: 'type', required: false, enum: LedgerType })
  @ApiQuery({ name: 'assetType', required: false, enum: AssetType })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'pageSize', required: false, type: Number })
  @ApiResponse({ status: 200, description: '返回分类账流水' })
  async getLedgers(
    @Param('name') name: string,
    @Query('type') type?: LedgerType,
    @Query('assetType') assetType?: AssetType,
    @Query('page') page?: string,
    @Query('pageSize') pageSize?: string,
  ) {
    const result = await this.marketMakerService.getLedgers(name, {
      type,
      assetType,
      page: page ? parseInt(page, 10) : undefined,
      pageSize: pageSize ? parseInt(pageSize, 10) : undefined,
    });

    return {
      success: true,
      data: result.data.map((l) => ({
        id: l.id,
        type: l.type,
        assetType: l.assetType,
        amount: l.amount.toString(),
        balanceBefore: l.balanceBefore.toString(),
        balanceAfter: l.balanceAfter.toString(),
        tradeNo: l.tradeNo,
        orderNo: l.orderNo,
        counterpartySeq: l.counterpartySeq,
        price: l.price?.toString(),
        quantity: l.quantity?.toString(),
        memo: l.memo,
        createdAt: l.createdAt,
      })),
      total: result.total,
    };
  }

  // ============ 双边挂单（深度做市）相关端点 ============

  @Post(':name/start-maker')
  @Public()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '启动挂单模式（双边深度）' })
  @ApiResponse({ status: 200, description: '挂单模式已启动' })
  async startMaker(@Param('name') name: string) {
    await this.marketMakerService.startMaker(name);

    return {
      success: true,
      message: `做市商 ${name} 挂单模式已启动`,
    };
  }

  @Post(':name/stop-maker')
  @Public()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '停止挂单模式' })
  @ApiResponse({ status: 200, description: '挂单模式已停止' })
  async stopMaker(@Param('name') name: string) {
    await this.marketMakerService.stopMaker(name);

    return {
      success: true,
      message: `做市商 ${name} 挂单模式已停止`,
    };
  }

  @Post(':name/refresh-orders')
  @Public()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '手动刷新双边挂单' })
  @ApiResponse({ status: 200, description: '挂单刷新结果' })
  async refreshOrders(@Param('name') name: string) {
    const result = await this.marketMakerService.refreshMakerOrders(name);
    return result;
  }

  @Post(':name/cancel-all-orders')
  @Public()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '取消所有做市商挂单' })
  @ApiResponse({ status: 200, description: '取消结果' })
  async cancelAllOrders(@Param('name') name: string) {
    const cancelledCount = await this.marketMakerService.cancelAllMakerOrders(name);

    return {
      success: true,
      message: `已取消 ${cancelledCount} 个挂单`,
      cancelledCount,
    };
  }

  @Post(':name/maker-config')
  @Public()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '更新挂单配置' })
  @ApiResponse({ status: 200, description: '挂单配置更新成功' })
  async updateMakerConfig(@Param('name') name: string, @Body() dto: UpdateMakerConfigDto) {
    await this.marketMakerService.updateMakerConfig(name, dto);

    return {
      success: true,
      message: '挂单配置更新成功',
    };
  }

  @Get(':name/maker-orders')
  @Public()
  @ApiOperation({ summary: '获取做市商挂单列表' })
  @ApiQuery({ name: 'side', required: false, enum: ['BID', 'ASK'] })
  @ApiQuery({ name: 'status', required: false, enum: ['ACTIVE', 'FILLED', 'CANCELLED'] })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'pageSize', required: false, type: Number })
  @ApiResponse({ status: 200, description: '返回挂单列表' })
  async getMakerOrders(
    @Param('name') name: string,
    @Query('side') side?: 'BID' | 'ASK',
    @Query('status') status?: 'ACTIVE' | 'FILLED' | 'CANCELLED',
    @Query('page') page?: string,
    @Query('pageSize') pageSize?: string,
  ) {
    const result = await this.marketMakerService.getMakerOrders(name, {
      side,
      status,
      page: page ? parseInt(page, 10) : undefined,
      pageSize: pageSize ? parseInt(pageSize, 10) : undefined,
    });

    return {
      success: true,
      data: result.data.map((o) => ({
        id: o.id,
        orderNo: o.orderNo,
        side: o.side,
        level: o.level,
        price: o.price.toString(),
        quantity: o.quantity.toString(),
        remainingQty: o.remainingQty.toString(),
        status: o.status,
        createdAt: o.createdAt,
      })),
      total: result.total,
    };
  }

  @Get('depth')
  @Public()
  @ApiOperation({ summary: '获取订单簿深度' })
  @ApiQuery({ name: 'levels', required: false, type: Number, description: '深度档位数（默认10）' })
  @ApiResponse({ status: 200, description: '返回深度数据' })
  async getDepth(@Query('levels') levels?: string) {
    const depth = await this.marketMakerService.getDepth(levels ? parseInt(levels, 10) : 10);

    return {
      success: true,
      ...depth,
    };
  }
}
