import { Injectable, NotFoundException, BadRequestException, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { PrismaService } from '../../../prisma/prisma.service';
import { TelegramApiService } from './telegram-api.service';
import { Prisma } from '@prisma/client';
import { CreateBotDto } from '../dto/create-bot.dto';
import { UpdateBotDto } from '../dto/update-bot.dto';

@Injectable()
export class BotManagerService {
  private readonly logger = new Logger(BotManagerService.name);

  constructor(
    private readonly prisma: PrismaService,
    private readonly config: ConfigService,
    private readonly telegramApi: TelegramApiService,
  ) {}

  async create(clubId: string, dto: CreateBotDto) {
    // Validate token by calling getMe
    const botInfo = await this.telegramApi.getMe(dto.token);

    return this.prisma.tgBot.create({
      data: {
        clubId,
        name: dto.name,
        token: dto.token,
        username: botInfo.username,
        settings: (dto.settings ?? {}) as Prisma.InputJsonValue,
      },
    });
  }

  async findAll(clubId: string) {
    return this.prisma.tgBot.findMany({
      where: { clubId },
      orderBy: { createdAt: 'desc' },
      select: {
        id: true,
        clubId: true,
        name: true,
        username: true,
        isActive: true,
        scenarioId: true,
        settings: true,
        createdAt: true,
        updatedAt: true,
        _count: { select: { subscribers: true } },
      },
    });
  }

  async findOne(clubId: string, id: string) {
    const bot = await this.prisma.tgBot.findFirst({
      where: { id, clubId },
      include: {
        scenario: { select: { id: true, name: true, isPublished: true } },
        _count: { select: { subscribers: true, broadcasts: true } },
      },
    });

    if (!bot) throw new NotFoundException('Bot not found');

    return { ...bot, token: undefined };
  }

  async update(clubId: string, id: string, dto: UpdateBotDto) {
    const bot = await this.prisma.tgBot.findFirst({ where: { id, clubId } });
    if (!bot) throw new NotFoundException('Bot not found');

    if (dto.token && dto.token !== bot.token) {
      await this.telegramApi.getMe(dto.token);
    }

    const data: Prisma.TgBotUpdateInput = {};
    if (dto.name) data.name = dto.name;
    if (dto.token) data.token = dto.token;
    if (dto.scenarioId !== undefined) {
      data.scenario = dto.scenarioId ? { connect: { id: dto.scenarioId } } : { disconnect: true };
    }
    if (dto.settings) data.settings = dto.settings as Prisma.InputJsonValue;

    return this.prisma.tgBot.update({ where: { id }, data });
  }

  async remove(clubId: string, id: string) {
    const bot = await this.prisma.tgBot.findFirst({ where: { id, clubId } });
    if (!bot) throw new NotFoundException('Bot not found');

    if (bot.isActive) {
      await this.telegramApi.deleteWebhook(bot.token).catch(() => {});
    }

    await this.prisma.tgBot.delete({ where: { id } });
    return { deleted: true };
  }

  async activate(clubId: string, id: string) {
    const bot = await this.prisma.tgBot.findFirst({ where: { id, clubId } });
    if (!bot) throw new NotFoundException('Bot not found');
    if (bot.isActive) throw new BadRequestException('Bot is already active');

    const apiBaseUrl = this.config.get<string>('app.apiBaseUrl', 'https://api.myfitcrm.ru');
    const webhookUrl = `${apiBaseUrl}/v1/telegram-bot/webhook/${bot.id}`;

    await this.telegramApi.setWebhook(bot.token, webhookUrl);

    return this.prisma.tgBot.update({
      where: { id },
      data: { isActive: true, webhookUrl },
    });
  }

  async deactivate(clubId: string, id: string) {
    const bot = await this.prisma.tgBot.findFirst({ where: { id, clubId } });
    if (!bot) throw new NotFoundException('Bot not found');
    if (!bot.isActive) throw new BadRequestException('Bot is not active');

    await this.telegramApi.deleteWebhook(bot.token).catch(() => {});

    return this.prisma.tgBot.update({
      where: { id },
      data: { isActive: false, webhookUrl: null },
    });
  }

  /** Internal: get bot with token for processing */
  async getWithToken(botId: string) {
    const bot = await this.prisma.tgBot.findUnique({
      where: { id: botId },
      include: { scenario: true },
    });
    if (!bot) throw new NotFoundException('Bot not found');
    return bot;
  }
}
