import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, MoreThan } from 'typeorm';
import { OnEvent } from '@nestjs/event-emitter';
import { CommunityGoal } from './community-goal.entity';
import { CommunityContribution } from './community-contribution.entity';
import { ActiveBoost } from './active-boost.entity';

export interface CommunityContributeEvent {
  characterId: string;
  type: string;    // matches communityGoal.criteriaType
  increment: number;
}

@Injectable()
export class CommunityService {
  constructor(
    @InjectRepository(CommunityGoal)
    private readonly goalRepo: Repository<CommunityGoal>,
    @InjectRepository(CommunityContribution)
    private readonly contributionRepo: Repository<CommunityContribution>,
    @InjectRepository(ActiveBoost)
    private readonly boostRepo: Repository<ActiveBoost>,
  ) {}

  async getActiveGoals() {
    const now = new Date();
    return this.goalRepo.find({
      where: { periodEnd: MoreThan(now) },
      order: { periodStart: 'ASC' },
    });
  }

  async getTopContributors(goalId: string, limit = 10) {
    return this.contributionRepo.find({
      where: { communityGoalId: goalId },
      order: { contributionValue: 'DESC' },
      take: limit,
      relations: ['character'],
    });
  }

  async getActiveBoosts() {
    const now = new Date();
    return this.boostRepo.find({
      where: { expiresAt: MoreThan(now) },
    });
  }

  async getActiveMultiplier(boostType: string): Promise<number> {
    const now = new Date();
    const boosts = await this.boostRepo.find({
      where: { boostType, expiresAt: MoreThan(now) },
    });
    if (!boosts.length) return 1.0;
    // Stack multiplicatively
    return boosts.reduce((acc, b) => acc * Number(b.multiplier), 1.0);
  }

  @OnEvent('community.contribute')
  async handleContribution(event: CommunityContributeEvent) {
    const { characterId, type, increment } = event;

    // Find active goals matching this criteria
    const now = new Date();
    const goals = await this.goalRepo
      .createQueryBuilder('g')
      .where('g.criteria_type = :type', { type })
      .andWhere('g.completed = false')
      .andWhere('g.period_end > :now', { now })
      .getMany();

    for (const goal of goals) {
      // Update individual contribution
      let contribution = await this.contributionRepo.findOne({
        where: { communityGoalId: goal.id, characterId },
      });
      if (!contribution) {
        contribution = this.contributionRepo.create({
          communityGoalId: goal.id,
          characterId,
          contributionValue: 0,
        });
      }
      contribution.contributionValue = Number(contribution.contributionValue) + increment;
      await this.contributionRepo.save(contribution);

      // Update global counter
      goal.currentValue = Number(goal.currentValue) + increment;

      // Check completion
      if (goal.currentValue >= goal.targetValue && !goal.completed) {
        goal.completed = true;
        goal.completedAt = new Date();

        // Create boost
        const expiresAt = new Date();
        expiresAt.setHours(expiresAt.getHours() + goal.rewardDurationHours);

        const boost = this.boostRepo.create({
          boostType: goal.rewardType,
          multiplier: goal.rewardMultiplier,
          expiresAt,
          sourceGoalId: goal.id,
        });
        await this.boostRepo.save(boost);
      }

      await this.goalRepo.save(goal);
    }
  }
}
