import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, DataSource } from 'typeorm';
import { Trip } from '@/entities/trip.entity';
import { User } from '@/entities/user.entity';
import { TripFund } from '@/entities/trip-funds.entity';
import { CreateMultipleTripFundDto } from './dto/create-multiple-trip-fund.dto';
import { randomUUID } from 'crypto';

@Injectable()
export class TripFundService {
  constructor(
    @InjectRepository(TripFund)
    private readonly fundRepo: Repository<TripFund>,

    @InjectRepository(Trip)
    private readonly tripRepo: Repository<Trip>,

    @InjectRepository(User)
    private readonly userRepo: Repository<User>,

    private readonly dataSource: DataSource,
  ) {}

  async upsertMultiple(tripId: string, dto: CreateMultipleTripFundDto) {
    const trip = await this.tripRepo.findOne({
      where: { id: tripId },
    });
    if (!trip) throw new NotFoundException('Không tìm thấy chuyến đi');

    const userIds = dto.contributions.map((c) => c.userId);

    const users = await this.userRepo.findByIds(userIds);
    const userMap = new Map(users.map((u) => [u.id, u]));

    // validate user tồn tại
    for (const item of dto.contributions) {
      if (!userMap.has(item.userId)) {
        throw new NotFoundException(`Không tìm thấy ${item.userId}`);
      }
      if (item.amount <= 0) {
        throw new Error(`Amount must be > 0`);
      }
    }

    // transaction + raw SQL (atomic)
    await this.dataSource.transaction(async (manager) => {
      for (const item of dto.contributions) {
        await manager.query(
          `
            INSERT INTO trip_funds (id, trip_id, user_id, amount, note)
            VALUES (?, ?, ?, ?, ?)
            ON DUPLICATE KEY UPDATE
                amount = amount + VALUES(amount),
                note = VALUES(note)
            `,
          [randomUUID(), tripId, item.userId, item.amount, dto.note || null],
        );
      }
    });

    return { success: true };
  }

  async findByTrip(tripId: string) {
    return this.fundRepo
      .createQueryBuilder('fund')
      .leftJoin('fund.user', 'user')
      .select([
        'fund.id',
        'fund.amount',
        'fund.note',
        'fund.createdAt',
        'user.id',
        'user.name',
        'user.phone',
        'user.email',
        'user.avatar',
      ])
      .where('fund.trip_id = :tripId', { tripId })
      .orderBy('fund.createdAt', 'DESC')
      .getMany();
  }

  async remove(tripId: string, userId: string) {
    const fund = await this.fundRepo.findOne({
      where: {
        trip: { id: tripId },
        user: { id: userId },
      },
    });

    if (!fund) throw new NotFoundException('Không tìm thấy quỹ');

    return this.fundRepo.remove(fund);
  }
}
