import {
  Body,
  Controller,
  Delete,
  Get,
  HttpCode,
  Param,
  ParseUUIDPipe,
  Post,
  Query,
  Req,
  Res,
} from '@nestjs/common';
import { RequirePermissions } from '@/common/decorators/permissions.decorator';
import { CurrentUser } from '@/common/decorators/current-user.decorator';
import { Auditable } from '@core/observability/audit/decorators/auditable.decorator';
import { AiUsageTokenService } from '../services/token.service';
import { AiUsageDashboardService } from '../services/dashboard.service';
import { CreateTokenDto, DashboardQueryDto } from '../dto';
import type { Response } from 'express';

@Controller('ai-usage/me')
export class AiUsageMeController {
  constructor(
    private readonly tokenSvc: AiUsageTokenService,
    private readonly dashboardSvc: AiUsageDashboardService,
  ) {}

  @Get('tokens')
  @RequirePermissions('ai-usage:view-own')
  async listMyTokens(@CurrentUser('userId') userId: string) {
    const items = await this.tokenSvc.listForUser(userId);
    return { items };
  }

  @Post('tokens')
  @Auditable()
  @RequirePermissions('ai-usage:manage-tokens-own')
  async createMyToken(
    @Body() dto: CreateTokenDto,
    @CurrentUser('userId') userId: string,
    @Req() req: any,
  ) {
    const organizationId = req.user?.currentOrganizationId;
    return this.tokenSvc.create({ userId, organizationId, name: dto.name });
  }

  @Delete('tokens/:id')
  @Auditable()
  @HttpCode(204)
  @RequirePermissions('ai-usage:manage-tokens-own')
  async revokeMyToken(@Param('id', ParseUUIDPipe) id: string, @CurrentUser('userId') userId: string) {
    await this.tokenSvc.revoke({ tokenId: id, userId, isAdmin: false, revokedById: userId });
  }

  @Get('summary')
  @RequirePermissions('ai-usage:view-own')
  async summary(
    @Query() q: DashboardQueryDto,
    @CurrentUser('userId') userId: string,
    @Req() req: any,
  ) {
    const organizationId = req.user?.currentOrganizationId;
    const range = this.dashboardSvc.resolveRange(q.period, q.from, q.to);
    return this.dashboardSvc.summary({ organizationId, userId }, range);
  }

  @Get('trend')
  @RequirePermissions('ai-usage:view-own')
  async trend(
    @Query() q: DashboardQueryDto,
    @CurrentUser('userId') userId: string,
    @Req() req: any,
  ) {
    const organizationId = req.user?.currentOrganizationId;
    const range = this.dashboardSvc.resolveRange(q.period, q.from, q.to);
    return this.dashboardSvc.trend({ organizationId, userId }, range, q.granularity ?? 'day', 'none');
  }

  @Get('breakdown')
  @RequirePermissions('ai-usage:view-own')
  async breakdown(
    @Query() q: DashboardQueryDto,
    @CurrentUser('userId') userId: string,
    @Req() req: any,
  ) {
    const organizationId = req.user?.currentOrganizationId;
    const range = this.dashboardSvc.resolveRange(q.period, q.from, q.to);
    return this.dashboardSvc.breakdown(
      { organizationId, userId },
      range,
      (q.by ?? 'project') as any,
      q.page ?? 1,
      q.pageSize ?? 20,
    );
  }

  @Get('devices')
  @RequirePermissions('ai-usage:view-own')
  async myDevices(@CurrentUser('userId') userId: string) {
    return { items: await this.dashboardSvc.listMyDevices(userId) };
  }

  @Get('blocks')
  @RequirePermissions('ai-usage:view-own')
  async myBlocks(@CurrentUser('userId') userId: string, @Req() req: any) {
    const organizationId = req.user?.currentOrganizationId;
    return this.dashboardSvc.listBlocks({ organizationId, userId });
  }

  // ===== v1.1 富 metadata 自查 =====

  @Get('tool-frequency')
  @RequirePermissions('ai-usage:view-own')
  async myToolFrequency(@Query() q: DashboardQueryDto, @CurrentUser('userId') userId: string, @Req() req: any) {
    const organizationId = req.user?.currentOrganizationId;
    const range = this.dashboardSvc.resolveRange(q.period, q.from, q.to);
    return this.dashboardSvc.toolFrequency({ organizationId, userId }, range);
  }

  @Get('session-stats')
  @RequirePermissions('ai-usage:view-own')
  async mySessionStats(
    @Query() q: DashboardQueryDto & { projectBasename?: string },
    @CurrentUser('userId') userId: string,
    @Req() req: any,
  ) {
    const organizationId = req.user?.currentOrganizationId;
    const range = this.dashboardSvc.resolveRange(q.period, q.from, q.to);
    return this.dashboardSvc.sessionStats(
      { organizationId, userId },
      range,
      { projectBasename: q.projectBasename },
      q.page ?? 1,
      q.pageSize ?? 50,
    );
  }

  @Get('sessions/:sessionId/turns')
  @RequirePermissions('ai-usage:view-own')
  async mySessionTurns(@Param('sessionId') sessionId: string, @CurrentUser('userId') userId: string, @Req() req: any) {
    const organizationId = req.user?.currentOrganizationId;
    return this.dashboardSvc.sessionTurns({ organizationId, userId }, sessionId);
  }

  @Get('turn-gap-distribution')
  @RequirePermissions('ai-usage:view-own')
  async myTurnGapDistribution(@Query() q: DashboardQueryDto, @CurrentUser('userId') userId: string, @Req() req: any) {
    const organizationId = req.user?.currentOrganizationId;
    const range = this.dashboardSvc.resolveRange(q.period, q.from, q.to);
    return this.dashboardSvc.turnGapDistribution({ organizationId, userId }, range);
  }

  @Get('service-tier-mix')
  @RequirePermissions('ai-usage:view-own')
  async myServiceTierMix(@Query() q: DashboardQueryDto, @CurrentUser('userId') userId: string, @Req() req: any) {
    const organizationId = req.user?.currentOrganizationId;
    const range = this.dashboardSvc.resolveRange(q.period, q.from, q.to);
    return this.dashboardSvc.serviceTierMix({ organizationId, userId }, range);
  }

  @Get('export')
  @RequirePermissions('ai-usage:view-own')
  async export(
    @Query() q: DashboardQueryDto,
    @CurrentUser('userId') userId: string,
    @Req() req: any,
    @Res() res: Response,
  ) {
    const organizationId = req.user?.currentOrganizationId;
    const range = this.dashboardSvc.resolveRange(q.period, q.from, q.to);
    const breakdown = await this.dashboardSvc.breakdown({ organizationId, userId }, range, 'project', 1, 200);
    res.setHeader('Content-Type', 'text/csv; charset=utf-8');
    res.setHeader('Content-Disposition', `attachment; filename="my-ai-usage-${range.from.toISOString().slice(0, 10)}.csv"`);
    res.write('﻿'); // UTF-8 BOM
    res.write('project,tokens,cost_usd,share\n');
    for (const row of breakdown.items) {
      const cell = `"${String(row.key).replace(/"/g, '""')}"`;
      res.write(`${cell},${row.tokens},${row.costUsd},${row.share.toFixed(4)}\n`);
    }
    res.end();
  }
}
