import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { History } from './entities/history.entity';
import { UpsertHistoryDto } from './dto/upsert-history.dto';
import { PaginationOptions } from '../common/interfaces';

@Injectable()
export class HistoryService {
  constructor(
    @InjectRepository(History)
    private readonly historyRepository: Repository<History>,
  ) {}

  async upsert(userId: string, upsertHistoryDto: UpsertHistoryDto): Promise<History> {
    const existing = await this.historyRepository.findOne({
      where: {
        userId,
        contentId: upsertHistoryDto.contentId,
        contentType: upsertHistoryDto.contentType,
      },
    });

    if (existing) {
      existing.progressSeconds = upsertHistoryDto.progressSeconds;
      existing.totalSeconds = upsertHistoryDto.totalSeconds;
      return this.historyRepository.save(existing);
    }

    const history = this.historyRepository.create({
      userId,
      ...upsertHistoryDto,
    });

    return this.historyRepository.save(history);
  }

  async findAllByUser(userId: string, pagination: PaginationOptions) {
    const { page, limit } = pagination;
    const skip = (page - 1) * limit;

    const [history, total] = await this.historyRepository.findAndCount({
      where: { userId },
      order: { watchedAt: 'DESC' },
      skip,
      take: limit,
    });

    return {
      data: history,
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit),
    };
  }

  async getContinueWatching(userId: string) {
    // Items where progress is between 5% and 95% of total
    const history = await this.historyRepository
      .createQueryBuilder('history')
      .where('history.userId = :userId', { userId })
      .andWhere('history.totalSeconds > 0')
      .andWhere('history.progressSeconds > 0')
      .andWhere(
        'CAST(history.progressSeconds AS FLOAT) / CAST(history.totalSeconds AS FLOAT) < 0.95',
      )
      .andWhere(
        'CAST(history.progressSeconds AS FLOAT) / CAST(history.totalSeconds AS FLOAT) > 0.05',
      )
      .orderBy('history.watchedAt', 'DESC')
      .take(20)
      .getMany();

    return history;
  }

  async remove(id: string, userId: string): Promise<void> {
    const history = await this.historyRepository.findOne({
      where: { id, userId },
    });

    if (!history) {
      throw new NotFoundException(`History entry with ID "${id}" not found`);
    }

    await this.historyRepository.remove(history);
  }
}
