import { Currency, CurrencyModel } from '../models/Currency';
import currencyRepository from '../repositories/CurrencyRepository';
import { logger } from '../utils/logger';

export class CurrencyService {
  async getCurrencies(): Promise<Currency[]> {
    try {
      const currencies = await currencyRepository.findAll();
      logger.info(`[CurrencyService] Retrieved ${currencies.length} currencies`);
      return currencies;
    } catch (error) {
      logger.error('[CurrencyService] Error getting currencies:', error);
      throw new Error('Failed to get currencies');
    }
  }

  async getCurrencyByCode(code: string): Promise<Currency | null> {
    try {
      const currency = await currencyRepository.findByCode(code);
      if (currency) {
        logger.info(`[CurrencyService] Retrieved currency: ${code}`);
      } else {
        logger.info(`[CurrencyService] Currency not found: ${code}`);
      }
      return currency;
    } catch (error) {
      logger.error('[CurrencyService] Error getting currency by code:', error);
      throw new Error('Failed to get currency by code');
    }
  }

  async getDefaultCurrency(): Promise<Currency | null> {
    try {
      const currency = await currencyRepository.findDefault();
      if (currency) {
        logger.info(`[CurrencyService] Retrieved default currency: ${currency.code}`);
      } else {
        logger.info('[CurrencyService] No default currency found');
      }
      return currency;
    } catch (error) {
      logger.error('[CurrencyService] Error getting default currency:', error);
      throw new Error('Failed to get default currency');
    }
  }

  async createCurrency(data: {
    code: string;
    name: string;
    symbol: string;
    decimal_places?: number;
    format: string;
    is_default?: boolean;
    created_by: string;
  }): Promise<Currency> {
    try {
      // 验证货币代码是否已存在
      const exists = await currencyRepository.exists(data.code);
      if (exists) {
        throw new Error(`Currency with code ${data.code} already exists`);
      }

      const currencyData: Omit<Currency, 'id' | 'created_at' | 'updated_at'> = {
        code: data.code.toUpperCase(),
        name: data.name,
        symbol: data.symbol,
        decimal_places: data.decimal_places || 2,
        format: data.format,
        is_active: true,
        is_default: data.is_default || false,
        created_by: data.created_by,
        updated_by: data.created_by,
      };

      const currency = CurrencyModel.create(currencyData);
      const createdCurrency = await currencyRepository.create(currency);

      // 如果设置为默认货币，更新其他货币
      if (data.is_default) {
        await currencyRepository.setDefault(createdCurrency.id);
      }

      logger.info(`[CurrencyService] Created currency: ${createdCurrency.code}`);
      return createdCurrency;
    } catch (error) {
      logger.error('[CurrencyService] Error creating currency:', error);
      throw new Error('Failed to create currency');
    }
  }

  async updateCurrency(id: string, data: {
    name?: string;
    symbol?: string;
    decimal_places?: number;
    format?: string;
    is_active?: boolean;
    is_default?: boolean;
    updated_by: string;
  }): Promise<Currency | null> {
    try {
      const currency = await currencyRepository.findById(id);
      if (!currency) {
        throw new Error('Currency not found');
      }

      const updateData: Partial<Omit<Currency, 'id' | 'created_at'>> = {
        updated_by: data.updated_by,
      };

      if (data.name !== undefined) updateData.name = data.name;
      if (data.symbol !== undefined) updateData.symbol = data.symbol;
      if (data.decimal_places !== undefined) updateData.decimal_places = data.decimal_places;
      if (data.format !== undefined) updateData.format = data.format;
      if (data.is_active !== undefined) updateData.is_active = data.is_active;

      const updatedCurrency = await currencyRepository.update(id, updateData);

      // 如果设置为默认货币，更新其他货币
      if (data.is_default) {
        await currencyRepository.setDefault(id);
      }

      logger.info(`[CurrencyService] Updated currency: ${updatedCurrency.code}`);
      return updatedCurrency;
    } catch (error) {
      logger.error('[CurrencyService] Error updating currency:', error);
      throw new Error('Failed to update currency');
    }
  }

  async deactivateCurrency(id: string, updated_by: string): Promise<Currency | null> {
    try {
      const currency = await currencyRepository.findById(id);
      if (!currency) {
        throw new Error('Currency not found');
      }

      // 不能停用默认货币
      if (currency.is_default) {
        throw new Error('Cannot deactivate default currency');
      }

      const deactivatedCurrency = await currencyRepository.deactivate(id);
      logger.info(`[CurrencyService] Deactivated currency: ${deactivatedCurrency.code}`);
      return deactivatedCurrency;
    } catch (error) {
      logger.error('[CurrencyService] Error deactivating currency:', error);
      throw new Error('Failed to deactivate currency');
    }
  }

  async setDefaultCurrency(id: string, updated_by: string): Promise<Currency | null> {
    try {
      const currency = await currencyRepository.findById(id);
      if (!currency) {
        throw new Error('Currency not found');
      }

      if (!currency.is_active) {
        throw new Error('Cannot set inactive currency as default');
      }

      const defaultCurrency = await currencyRepository.setDefault(id);
      logger.info(`[CurrencyService] Set default currency: ${defaultCurrency.code}`);
      return defaultCurrency;
    } catch (error) {
      logger.error('[CurrencyService] Error setting default currency:', error);
      throw new Error('Failed to set default currency');
    }
  }

  async validateCurrencyCode(code: string): Promise<boolean> {
    try {
      const exists = await currencyRepository.exists(code);
      return exists;
    } catch (error) {
      logger.error('[CurrencyService] Error validating currency code:', error);
      throw new Error('Failed to validate currency code');
    }
  }
}

export default new CurrencyService();
