import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { CsvRateConfigOrmEntity } from '../entities/csv-rate-config.orm-entity';

/**
 * CSV Rate Config Repository Port
 *
 * Interface for CSV rate configuration operations
 */
export interface CsvRateConfigRepositoryPort {
  findAll(): Promise<CsvRateConfigOrmEntity[]>;
  findByCompanyName(companyName: string): Promise<CsvRateConfigOrmEntity | null>;
  findActiveConfigs(): Promise<CsvRateConfigOrmEntity[]>;
  create(config: Partial<CsvRateConfigOrmEntity>): Promise<CsvRateConfigOrmEntity>;
  update(id: string, config: Partial<CsvRateConfigOrmEntity>): Promise<CsvRateConfigOrmEntity>;
  delete(companyName: string): Promise<void>;
  exists(companyName: string): Promise<boolean>;
}

/**
 * TypeORM CSV Rate Config Repository
 *
 * Implementation of CSV rate configuration repository using TypeORM
 */
@Injectable()
export class TypeOrmCsvRateConfigRepository implements CsvRateConfigRepositoryPort {
  private readonly logger = new Logger(TypeOrmCsvRateConfigRepository.name);

  constructor(
    @InjectRepository(CsvRateConfigOrmEntity)
    private readonly repository: Repository<CsvRateConfigOrmEntity>
  ) {}

  /**
   * Find all CSV rate configurations
   */
  async findAll(): Promise<CsvRateConfigOrmEntity[]> {
    this.logger.log('Finding all CSV rate configs');
    return this.repository.find({
      order: { companyName: 'ASC' },
    });
  }

  /**
   * Find configuration by company name
   */
  async findByCompanyName(companyName: string): Promise<CsvRateConfigOrmEntity | null> {
    this.logger.log(`Finding CSV rate config for company: ${companyName}`);
    return this.repository.findOne({
      where: { companyName },
    });
  }

  /**
   * Find only active configurations
   */
  async findActiveConfigs(): Promise<CsvRateConfigOrmEntity[]> {
    this.logger.log('Finding active CSV rate configs');
    return this.repository.find({
      where: { isActive: true },
      order: { companyName: 'ASC' },
    });
  }

  /**
   * Create new CSV rate configuration
   */
  async create(config: Partial<CsvRateConfigOrmEntity>): Promise<CsvRateConfigOrmEntity> {
    this.logger.log(`Creating CSV rate config for company: ${config.companyName}`);

    // Check if company already exists
    const existing = await this.findByCompanyName(config.companyName!);
    if (existing) {
      throw new Error(`CSV rate config already exists for company: ${config.companyName}`);
    }

    const entity = this.repository.create({
      ...config,
      uploadedAt: new Date(),
      createdAt: new Date(),
      updatedAt: new Date(),
    });

    return this.repository.save(entity);
  }

  /**
   * Update existing CSV rate configuration
   */
  async update(
    id: string,
    config: Partial<CsvRateConfigOrmEntity>
  ): Promise<CsvRateConfigOrmEntity> {
    this.logger.log(`Updating CSV rate config: ${id}`);

    const existing = await this.repository.findOne({ where: { id } });
    if (!existing) {
      throw new Error(`CSV rate config not found: ${id}`);
    }

    // Update entity
    Object.assign(existing, config);
    existing.updatedAt = new Date();

    return this.repository.save(existing);
  }

  /**
   * Delete CSV rate configuration by company name
   */
  async delete(companyName: string): Promise<void> {
    this.logger.log(`Deleting CSV rate config for company: ${companyName}`);

    const result = await this.repository.delete({ companyName });

    if (result.affected === 0) {
      throw new Error(`CSV rate config not found for company: ${companyName}`);
    }

    this.logger.log(`Deleted CSV rate config for company: ${companyName}`);
  }

  /**
   * Check if configuration exists for company
   */
  async exists(companyName: string): Promise<boolean> {
    const count = await this.repository.count({
      where: { companyName },
    });
    return count > 0;
  }

  /**
   * Update row count and validation timestamp
   */
  async updateValidationInfo(
    companyName: string,
    rowCount: number,
    validationResult: { valid: boolean; errors: string[] }
  ): Promise<void> {
    this.logger.log(`Updating validation info for company: ${companyName}`);

    const config = await this.findByCompanyName(companyName);
    if (!config) {
      throw new Error(`CSV rate config not found for company: ${companyName}`);
    }

    await this.repository.update(
      { companyName },
      {
        rowCount,
        lastValidatedAt: new Date(),
        metadata: {
          ...(config.metadata || {}),
          lastValidation: {
            valid: validationResult.valid,
            errors: validationResult.errors,
            timestamp: new Date().toISOString(),
          },
        } as any,
      }
    );
  }

  /**
   * Get all companies with API support
   */
  async findWithApiSupport(): Promise<CsvRateConfigOrmEntity[]> {
    this.logger.log('Finding CSV rate configs with API support');
    return this.repository.find({
      where: { hasApi: true, isActive: true },
      order: { companyName: 'ASC' },
    });
  }

  /**
   * Get all companies without API (CSV only)
   */
  async findCsvOnly(): Promise<CsvRateConfigOrmEntity[]> {
    this.logger.log('Finding CSV-only rate configs');
    return this.repository.find({
      where: { hasApi: false, isActive: true },
      order: { companyName: 'ASC' },
    });
  }
}
