import {
  Controller,
  Get,
  Query,
  Headers,
  UnauthorizedException,
  ParseIntPipe,
  DefaultValuePipe,
} from '@nestjs/common';
import { GetReferralListUseCase } from '../../../application/use-cases/get-referral-list.use-case';
import { ReferralRelationshipRepository } from '../../../infrastructure/repositories/referral-relationship.repository';
import { ReferralRewardRepository } from '../../../infrastructure/repositories/referral-reward.repository';
import { UserReferralRelationshipRepository } from '../../../infrastructure/repositories/user-referral-relationship.repository';
import { UserPointRepository } from '../../../infrastructure/repositories/user-point.repository';
import { ReferralStatus } from '../../../domain/entities/referral-relationship.entity';
import { RewardStatus } from '../../../domain/entities/referral-reward.entity';
import { UserReferralStatus } from '../../../domain/entities/user-referral-relationship.entity';
import * as jwt from 'jsonwebtoken';

/**
 * Platform-admin endpoints for managing the referral system.
 * Requires JWT with platform_admin or platform_super_admin role.
 */
@Controller('api/v1/referral/admin')
export class ReferralAdminController {
  constructor(
    private readonly getReferralList: GetReferralListUseCase,
    private readonly relationshipRepo: ReferralRelationshipRepository,
    private readonly rewardRepo: ReferralRewardRepository,
    private readonly userRelRepo: UserReferralRelationshipRepository,
    private readonly userPointRepo: UserPointRepository,
  ) {}

  // ── Tenant-level (B2B) ───────────────────────────────────────────────────

  /** GET /api/v1/referral/admin/relationships — all tenant referral relationships */
  @Get('relationships')
  async listRelationships(
    @Headers('authorization') auth: string,
    @Query('status') status: ReferralStatus | undefined,
    @Query('limit', new DefaultValuePipe(50), ParseIntPipe) limit: number,
    @Query('offset', new DefaultValuePipe(0), ParseIntPipe) offset: number,
  ) {
    this.requireAdmin(auth);
    return this.relationshipRepo.findAll(status, Math.min(limit, 200), offset);
  }

  /** GET /api/v1/referral/admin/rewards — all tenant reward records */
  @Get('rewards')
  async listRewards(
    @Headers('authorization') auth: string,
    @Query('status') status: RewardStatus | undefined,
    @Query('limit', new DefaultValuePipe(50), ParseIntPipe) limit: number,
    @Query('offset', new DefaultValuePipe(0), ParseIntPipe) offset: number,
  ) {
    this.requireAdmin(auth);
    return this.rewardRepo.findAll(status, Math.min(limit, 200), offset);
  }

  /** GET /api/v1/referral/admin/stats — global referral statistics */
  @Get('stats')
  async getStats(@Headers('authorization') auth: string) {
    this.requireAdmin(auth);
    const [totalRel, activeRel, pendingRewards, totalCircles, totalPointTxns] = await Promise.all([
      this.relationshipRepo.findAll(undefined, 1, 0).then((r) => r.total),
      this.relationshipRepo.findAll('ACTIVE', 1, 0).then((r) => r.total),
      this.rewardRepo.findAll('PENDING', 1, 0).then((r) => r.total),
      this.userRelRepo.findAll(undefined, 1, 0).then((r) => r.total),
      this.userPointRepo.getAllTransactions(1, 0).then((r) => r.total),
    ]);
    return {
      totalReferrals: totalRel,
      activeReferrals: activeRel,
      pendingRewards,
      totalUserCircles: totalCircles,
      totalPointTransactions: totalPointTxns,
    };
  }

  // ── User-level / personal circle (C2C) ──────────────────────────────────

  /** GET /api/v1/referral/admin/user-circles — all user-level circle relationships */
  @Get('user-circles')
  async listUserCircles(
    @Headers('authorization') auth: string,
    @Query('status') status: UserReferralStatus | undefined,
    @Query('limit', new DefaultValuePipe(50), ParseIntPipe) limit: number,
    @Query('offset', new DefaultValuePipe(0), ParseIntPipe) offset: number,
  ) {
    this.requireAdmin(auth);
    return this.userRelRepo.findAll(status, Math.min(limit, 200), offset);
  }

  /** GET /api/v1/referral/admin/user-points — all point transactions across users */
  @Get('user-points')
  async listUserPoints(
    @Headers('authorization') auth: string,
    @Query('limit', new DefaultValuePipe(50), ParseIntPipe) limit: number,
    @Query('offset', new DefaultValuePipe(0), ParseIntPipe) offset: number,
  ) {
    this.requireAdmin(auth);
    return this.userPointRepo.getAllTransactions(Math.min(limit, 200), offset);
  }

  /** GET /api/v1/referral/admin/user-balances — all user point balance summaries */
  @Get('user-balances')
  async listUserBalances(
    @Headers('authorization') auth: string,
    @Query('limit', new DefaultValuePipe(50), ParseIntPipe) limit: number,
    @Query('offset', new DefaultValuePipe(0), ParseIntPipe) offset: number,
  ) {
    this.requireAdmin(auth);
    return this.userPointRepo.getAllBalances(Math.min(limit, 200), offset);
  }

  // ── Helper ───────────────────────────────────────────────────────────────

  private requireAdmin(auth: string) {
    if (!auth?.startsWith('Bearer ')) {
      throw new UnauthorizedException('Missing authorization header');
    }
    const token = auth.slice(7);
    const secret = process.env.JWT_SECRET || 'dev-secret';
    try {
      const payload = jwt.verify(token, secret) as any;
      const roles: string[] = Array.isArray(payload.roles) ? payload.roles : [];
      if (
        !roles.includes('platform_admin') &&
        !roles.includes('platform_super_admin')
      ) {
        throw new UnauthorizedException('Admin role required');
      }
    } catch (err) {
      if (err instanceof UnauthorizedException) throw err;
      throw new UnauthorizedException('Invalid JWT');
    }
  }
}
