import { Injectable, BadRequestException, NotFoundException } from '@nestjs/common';
import { PrismaService } from '../../common/prisma.service';
import { CurrencyService } from '../currency/currency.service';
import { CreateCurrencyDto, UpdateCurrencyDto } from './currencies.dto';
import { AuditService } from '../../common/audit.service';

@Injectable()
export class CurrenciesService {
  constructor(
    private prisma: PrismaService,
    private currencyService: CurrencyService,
    private auditService: AuditService,
  ) {}

  async getAllCurrencies() {
    const rates = await this.prisma.currencyExchangeRate.findMany({
      distinct: ['toCurrency'],
      orderBy: { createdAt: 'desc' },
    });

    const base = {
      id: 'etb-base',
      code: 'ETB',
      name: 'Ethiopian Birr',
      symbol: 'Br',
      baseCurrencyCode: 'ETB',
      exchangeRate: 1,
      isActive: true,
      createdAt: new Date(),
      updatedAt: new Date(),
    };

    return [base, ...rates.map(rate => ({
      id: rate.id,
      code: rate.toCurrency,
      name: this.getCurrencyName(rate.toCurrency),
      symbol: this.getCurrencySymbol(rate.toCurrency),
      baseCurrencyCode: rate.fromCurrency,
      exchangeRate: Number(rate.rate),
      isActive: true,
      createdAt: rate.createdAt,
      updatedAt: rate.createdAt,
    }))];
  }

  async createCurrency(dto: CreateCurrencyDto) {
    const { code, name, symbol, baseCurrencyCode = 'ETB', exchangeRate } = dto;

    if (exchangeRate <= 0) {
      throw new BadRequestException('Exchange rate must be positive');
    }

    const rate = await this.prisma.currencyExchangeRate.create({
      data: {
        fromCurrency: baseCurrencyCode as any,
        toCurrency: code.toUpperCase() as any,
        rate: exchangeRate,
        source: 'MANUAL',
      },
    });

    await this.auditService.log({ action: 'CREATE', entityType: 'Currency', entityId: rate.id, newData: { code, exchangeRate } });
    return {
      id: rate.id,
      code: rate.toCurrency,
      name,
      symbol,
      baseCurrencyCode: rate.fromCurrency,
      exchangeRate: Number(rate.rate),
      isActive: true,
      createdAt: rate.createdAt,
      updatedAt: rate.createdAt,
    };
  }

  async updateCurrency(id: string, dto: UpdateCurrencyDto) {
    const existing = await this.prisma.currencyExchangeRate.findUnique({
      where: { id },
    });

    if (!existing) {
      throw new NotFoundException('Currency not found');
    }

    if (dto.exchangeRate !== undefined && dto.exchangeRate <= 0) {
      throw new BadRequestException('Exchange rate must be positive');
    }

    // Upsert today's record so getRateOrThrow (orderBy effectiveDate desc) picks it up
    const updated = await this.currencyService.upsertRate(
      existing.fromCurrency,
      existing.toCurrency,
      dto.exchangeRate ?? Number(existing.rate),
      undefined,
      'MANUAL',
    );

    await this.auditService.log({ action: 'UPDATE', entityType: 'Currency', entityId: updated.id, newData: { exchangeRate: Number(updated.rate) } });
    return {
      id: updated.id,
      code: updated.toCurrency,
      name: dto.name || this.getCurrencyName(updated.toCurrency),
      symbol: dto.symbol || this.getCurrencySymbol(updated.toCurrency),
      baseCurrencyCode: updated.fromCurrency,
      exchangeRate: Number(updated.rate),
      isActive: true,
      createdAt: updated.createdAt,
      updatedAt: updated.createdAt,
    };
  }

  async syncExchangeRates() {
    // Placeholder: in production this would fetch from an external FX API.
    // For now, return the current rates as-is.
    const currencies = await this.getAllCurrencies();
    return { synced: true, rates: currencies };
  }

  async deleteCurrency(id: string) {
    const existing = await this.prisma.currencyExchangeRate.findUnique({
      where: { id },
    });

    if (!existing) {
      throw new NotFoundException('Currency not found');
    }

    // Delete all records for this currency pair so no stale rates remain
    await this.prisma.currencyExchangeRate.deleteMany({
      where: { fromCurrency: existing.fromCurrency, toCurrency: existing.toCurrency },
    });
    await this.auditService.log({ action: 'DELETE', entityType: 'Currency', entityId: id, oldData: { toCurrency: existing.toCurrency } });
    return { message: 'Currency deleted successfully' };
  }

  private getCurrencyName(code: string): string {
    const names: Record<string, string> = {
      ETB: 'Ethiopian Birr',
      USD: 'US Dollar',
      DJF: 'Djiboutian Franc',
    };
    return names[code] || code;
  }

  private getCurrencySymbol(code: string): string {
    const symbols: Record<string, string> = {
      ETB: 'Br',
      USD: '$',
      DJF: 'Fdj',
    };
    return symbols[code] || code;
  }
}
