import { Repository } from 'typeorm';
import { AppDataSource } from '../../config/typeorm.js';
import { Currency } from './entities/currency.entity.js';
import { NotFoundError, ConflictError } from '../../shared/errors/index.js';
import { logger } from '../../shared/utils/logger.js';

export interface CreateCurrencyDto {
  code: string;
  name: string;
  symbol: string;
  decimal_places?: number;
  decimals?: number; // Accept camelCase too
}

export interface UpdateCurrencyDto {
  name?: string;
  symbol?: string;
  decimal_places?: number;
  decimals?: number; // Accept camelCase too
  active?: boolean;
}

class CurrenciesService {
  private repository: Repository<Currency>;

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

  async findAll(activeOnly: boolean = false): Promise<Currency[]> {
    logger.debug('Finding all currencies', { activeOnly });

    const queryBuilder = this.repository
      .createQueryBuilder('currency')
      .orderBy('currency.code', 'ASC');

    if (activeOnly) {
      queryBuilder.where('currency.active = :active', { active: true });
    }

    return queryBuilder.getMany();
  }

  async findById(id: string): Promise<Currency> {
    logger.debug('Finding currency by id', { id });

    const currency = await this.repository.findOne({
      where: { id },
    });

    if (!currency) {
      throw new NotFoundError('Moneda no encontrada');
    }

    return currency;
  }

  async findByCode(code: string): Promise<Currency | null> {
    logger.debug('Finding currency by code', { code });

    return this.repository.findOne({
      where: { code: code.toUpperCase() },
    });
  }

  async create(dto: CreateCurrencyDto): Promise<Currency> {
    logger.debug('Creating currency', { code: dto.code });

    const existing = await this.findByCode(dto.code);
    if (existing) {
      throw new ConflictError(`Ya existe una moneda con código ${dto.code}`);
    }

    // Accept both snake_case and camelCase
    const decimals = dto.decimal_places ?? dto.decimals ?? 2;

    const currency = this.repository.create({
      code: dto.code.toUpperCase(),
      name: dto.name,
      symbol: dto.symbol,
      decimals,
    });

    const saved = await this.repository.save(currency);
    logger.info('Currency created', { id: saved.id, code: saved.code });

    return saved;
  }

  async update(id: string, dto: UpdateCurrencyDto): Promise<Currency> {
    logger.debug('Updating currency', { id });

    const currency = await this.findById(id);

    // Accept both snake_case and camelCase
    const decimals = dto.decimal_places ?? dto.decimals;

    if (dto.name !== undefined) {
      currency.name = dto.name;
    }
    if (dto.symbol !== undefined) {
      currency.symbol = dto.symbol;
    }
    if (decimals !== undefined) {
      currency.decimals = decimals;
    }
    if (dto.active !== undefined) {
      currency.active = dto.active;
    }

    const updated = await this.repository.save(currency);
    logger.info('Currency updated', { id: updated.id, code: updated.code });

    return updated;
  }
}

export const currenciesService = new CurrenciesService();
