/**
 * WhatsApp Account Service
 * Service for managing WhatsApp Business accounts
 *
 * @module WhatsApp
 */

import { Repository, FindOptionsWhere } from 'typeorm';
import { AppDataSource } from '../../../shared/database/typeorm.config';
import { WhatsAppAccount, AccountStatus } from '../entities';

export interface ServiceContext {
  tenantId: string;
  userId?: string;
}

export interface CreateAccountDto {
  name: string;
  phoneNumber: string;
  phoneNumberId: string;
  businessAccountId: string;
  accessToken?: string;
  webhookVerifyToken?: string;
  webhookSecret?: string;
  businessName?: string;
  businessDescription?: string;
  businessCategory?: string;
  businessWebsite?: string;
  profilePictureUrl?: string;
  defaultLanguage?: string;
  autoReplyEnabled?: boolean;
  autoReplyMessage?: string;
  businessHours?: Record<string, any>;
  dailyMessageLimit?: number;
}

export interface UpdateAccountDto {
  name?: string;
  accessToken?: string;
  webhookVerifyToken?: string;
  webhookSecret?: string;
  businessName?: string;
  businessDescription?: string;
  businessCategory?: string;
  businessWebsite?: string;
  profilePictureUrl?: string;
  defaultLanguage?: string;
  autoReplyEnabled?: boolean;
  autoReplyMessage?: string;
  businessHours?: Record<string, any>;
  status?: AccountStatus;
  dailyMessageLimit?: number;
}

export interface AccountFilters {
  status?: AccountStatus;
  phoneNumber?: string;
}

export class WhatsAppAccountService {
  private repository: Repository<WhatsAppAccount>;

  constructor() {
    this.repository = AppDataSource.getRepository(WhatsAppAccount);
  }

  async findAll(ctx: ServiceContext, filters?: AccountFilters): Promise<WhatsAppAccount[]> {
    const where: FindOptionsWhere<WhatsAppAccount> = {
      tenantId: ctx.tenantId,
    };

    if (filters?.status) {
      where.status = filters.status;
    }

    if (filters?.phoneNumber) {
      where.phoneNumber = filters.phoneNumber;
    }

    return this.repository.find({
      where,
      order: { createdAt: 'DESC' },
    });
  }

  async findById(ctx: ServiceContext, id: string): Promise<WhatsAppAccount | null> {
    return this.repository.findOne({
      where: { id, tenantId: ctx.tenantId },
    });
  }

  async findByPhoneNumber(ctx: ServiceContext, phoneNumber: string): Promise<WhatsAppAccount | null> {
    return this.repository.findOne({
      where: { phoneNumber, tenantId: ctx.tenantId },
    });
  }

  async findActive(ctx: ServiceContext): Promise<WhatsAppAccount[]> {
    return this.repository.find({
      where: { tenantId: ctx.tenantId, status: 'active' },
      order: { createdAt: 'DESC' },
    });
  }

  async create(ctx: ServiceContext, data: CreateAccountDto): Promise<WhatsAppAccount> {
    const account = this.repository.create({
      ...data,
      tenantId: ctx.tenantId,
      createdBy: ctx.userId,
      status: 'pending',
    });
    return this.repository.save(account);
  }

  async update(ctx: ServiceContext, id: string, data: UpdateAccountDto): Promise<WhatsAppAccount | null> {
    const account = await this.findById(ctx, id);
    if (!account) {
      return null;
    }

    Object.assign(account, data);
    return this.repository.save(account);
  }

  async delete(ctx: ServiceContext, id: string): Promise<boolean> {
    const result = await this.repository.delete({ id, tenantId: ctx.tenantId });
    return result.affected ? result.affected > 0 : false;
  }

  async activate(ctx: ServiceContext, id: string): Promise<WhatsAppAccount | null> {
    const account = await this.findById(ctx, id);
    if (!account) {
      return null;
    }

    account.status = 'active';
    account.verifiedAt = new Date();
    return this.repository.save(account);
  }

  async suspend(ctx: ServiceContext, id: string): Promise<WhatsAppAccount | null> {
    return this.update(ctx, id, { status: 'suspended' });
  }

  async disconnect(ctx: ServiceContext, id: string): Promise<WhatsAppAccount | null> {
    return this.update(ctx, id, { status: 'disconnected' });
  }

  async incrementMessagesSent(ctx: ServiceContext, id: string): Promise<void> {
    await this.repository.increment(
      { id, tenantId: ctx.tenantId },
      'messagesSentToday',
      1
    );
    await this.repository.increment(
      { id, tenantId: ctx.tenantId },
      'totalMessagesSent',
      1
    );
  }

  async incrementMessagesReceived(ctx: ServiceContext, id: string): Promise<void> {
    await this.repository.increment(
      { id, tenantId: ctx.tenantId },
      'totalMessagesReceived',
      1
    );
  }

  async resetDailyLimit(ctx: ServiceContext, id: string): Promise<void> {
    await this.repository.update(
      { id, tenantId: ctx.tenantId },
      {
        messagesSentToday: 0,
        lastLimitReset: new Date(),
      }
    );
  }

  async canSendMessage(ctx: ServiceContext, id: string): Promise<boolean> {
    const account = await this.findById(ctx, id);
    if (!account || account.status !== 'active') {
      return false;
    }

    return account.messagesSentToday < account.dailyMessageLimit;
  }

  async getStatistics(ctx: ServiceContext): Promise<{
    total: number;
    active: number;
    pending: number;
    suspended: number;
    disconnected: number;
  }> {
    const accounts = await this.repository.find({
      where: { tenantId: ctx.tenantId },
    });

    return {
      total: accounts.length,
      active: accounts.filter(a => a.status === 'active').length,
      pending: accounts.filter(a => a.status === 'pending').length,
      suspended: accounts.filter(a => a.status === 'suspended').length,
      disconnected: accounts.filter(a => a.status === 'disconnected').length,
    };
  }
}
