import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Channel } from './entities/channel.entity';
import { CreateChannelDto } from './dto/create-channel.dto';
import { UpdateChannelDto } from './dto/update-channel.dto';
import { PaginationOptions } from '../common/interfaces';

@Injectable()
export class ChannelsService {
  constructor(
    @InjectRepository(Channel)
    private readonly channelRepository: Repository<Channel>,
  ) {}

  async create(createChannelDto: CreateChannelDto): Promise<Channel> {
    const channel = this.channelRepository.create(createChannelDto);
    return this.channelRepository.save(channel);
  }

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

    const [channels, total] = await this.channelRepository.findAndCount({
      where: { isActive: true },
      relations: ['category'],
      order: { order: 'ASC', name: 'ASC' },
      skip,
      take: limit,
    });

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

  async findById(id: string): Promise<Channel> {
    const channel = await this.channelRepository.findOne({
      where: { id },
      relations: ['category'],
    });

    if (!channel) {
      throw new NotFoundException(`Channel with ID "${id}" not found`);
    }

    return channel;
  }

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

    const [channels, total] = await this.channelRepository.findAndCount({
      where: { categoryId, isActive: true },
      relations: ['category'],
      order: { order: 'ASC', name: 'ASC' },
      skip,
      take: limit,
    });

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

  async update(id: string, updateChannelDto: UpdateChannelDto): Promise<Channel> {
    const channel = await this.findById(id);
    Object.assign(channel, updateChannelDto);
    return this.channelRepository.save(channel);
  }

  async remove(id: string): Promise<void> {
    const channel = await this.findById(id);
    await this.channelRepository.remove(channel);
  }

  async count(): Promise<number> {
    return this.channelRepository.count({ where: { isActive: true } });
  }

  async search(query: string) {
    return this.channelRepository
      .createQueryBuilder('channel')
      .leftJoinAndSelect('channel.category', 'category')
      .where('channel.isActive = :isActive', { isActive: true })
      .andWhere('LOWER(channel.name) LIKE LOWER(:query)', { query: `%${query}%` })
      .orderBy('channel.order', 'ASC')
      .getMany();
  }
}
