import { Repository } from 'typeorm';
import { AppDataSource } from '../../config/typeorm.js';
import { Country } from './entities/country.entity.js';
import { State } from './entities/state.entity.js';
import { NotFoundError, ConflictError } from '../../shared/errors/index.js';
import { logger } from '../../shared/utils/logger.js';

export interface CreateCountryDto {
  code: string;
  name: string;
  phone_code?: string;
  phoneCode?: string; // Accept camelCase too
  currency_code?: string;
  currencyCode?: string; // Accept camelCase too
}

export interface UpdateCountryDto {
  name?: string;
  phone_code?: string | null;
  phoneCode?: string | null; // Accept camelCase too
  currency_code?: string | null;
  currencyCode?: string | null; // Accept camelCase too
}

// Extended interface for country with states
export interface CountryWithStates extends Country {
  states: State[];
}

class CountriesService {
  private repository: Repository<Country>;
  private stateRepository: Repository<State>;

  constructor() {
    this.repository = AppDataSource.getRepository(Country);
    this.stateRepository = AppDataSource.getRepository(State);
  }

  async findAll(): Promise<Country[]> {
    logger.debug('Finding all countries');

    return this.repository.find({
      order: { name: 'ASC' },
    });
  }

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

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

    if (!country) {
      throw new NotFoundError('País no encontrado');
    }

    return country;
  }

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

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

  async findWithStates(id: string): Promise<CountryWithStates> {
    logger.debug('Finding country with states', { id });

    const country = await this.findById(id);

    // Get states for this country
    const states = await this.stateRepository.find({
      where: { countryId: id },
      order: { name: 'ASC' },
    });

    return {
      ...country,
      states,
    };
  }

  async create(dto: CreateCountryDto): Promise<Country> {
    logger.debug('Creating country', { code: dto.code });

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

    // Accept both snake_case and camelCase
    const phoneCode = dto.phone_code ?? dto.phoneCode ?? null;
    const currencyCode = dto.currency_code ?? dto.currencyCode ?? null;

    const country = this.repository.create({
      code: dto.code.toUpperCase(),
      name: dto.name,
      phoneCode,
      currencyCode,
    });

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

    return saved;
  }

  async update(id: string, dto: UpdateCountryDto): Promise<Country> {
    logger.debug('Updating country', { id });

    const country = await this.findById(id);

    // Accept both snake_case and camelCase
    const phoneCode = dto.phone_code ?? dto.phoneCode;
    const currencyCode = dto.currency_code ?? dto.currencyCode;

    if (dto.name !== undefined) {
      country.name = dto.name;
    }
    if (phoneCode !== undefined) {
      country.phoneCode = phoneCode;
    }
    if (currencyCode !== undefined) {
      country.currencyCode = currencyCode;
    }

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

    return updated;
  }
}

export const countriesService = new CountriesService();
