import { handleKnownErrors } from 'src/common/utils/handle-error.util';
import { ERROR_CODES } from 'src/common/constants/error-string-constants';
import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { MergeInfoAnswerLocationMap } from 'src/common/entities/merge-info-answer-location-map.entity';

@Injectable()
export class MergeInfoAnswerLocationMapRepository {
  private readonly logger = new Logger(MergeInfoAnswerLocationMapRepository.name);

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

  /**
   * Create a new merge info mapping
   */
  async createEntity(data: Partial<MergeInfoAnswerLocationMap>): Promise<MergeInfoAnswerLocationMap> {
    try {
      const entity = this.repository.create(data);
      return await this.repository.save(entity);
    } catch (error) {
      this.logger.error(`Error creating merge info mapping: ${error.message}`, error.stack);
      handleKnownErrors(ERROR_CODES.MERGE_INFO_CREATE_FAILED, error);
    }
  }

  /**
   * Find all merge info mappings for a template
   */
  async findByTemplateId(templateId: number): Promise<MergeInfoAnswerLocationMap[]> {
    try {
      return await this.repository.find({
        where: { templateId, isActive: true },
        order: { keyName: 'ASC' },
      });
    } catch (error) {
      this.logger.error(
        `Error finding merge info mappings for template ${templateId}: ${error.message}`,
        error.stack,
      );
      handleKnownErrors(ERROR_CODES.MERGE_INFO_NOT_FOUND, error);
    }
  }

  /**
   * Find a specific merge info mapping by key name and template ID
   */
  async findByKeyAndTemplate(
    keyName: string,
    templateId: number,
  ): Promise<MergeInfoAnswerLocationMap | null> {
    try {
      return await this.repository.findOne({
        where: { keyName, templateId, isActive: true },
      });
    } catch (error) {
      this.logger.error(
        `Error finding merge info mapping for key ${keyName} and template ${templateId}: ${error.message}`,
        error.stack,
      );
      handleKnownErrors(ERROR_CODES.MERGE_INFO_NOT_FOUND, error);
    }
  }

  /**
   * Find all common merge info mappings
   */
  async findCommonMappings(): Promise<MergeInfoAnswerLocationMap[]> {
    try {
      return await this.repository.find({
        where: { isCommon: true, isActive: true },
        order: { keyName: 'ASC' },
      });
    } catch (error) {
      this.logger.error(`Error finding common merge info mappings: ${error.message}`, error.stack);
      handleKnownErrors(ERROR_CODES.MERGE_INFO_NOT_FOUND, error);
    }
  }

  /**
   * Update a merge info mapping
   */
  async update(
    id: number,
    data: Partial<MergeInfoAnswerLocationMap>,
  ): Promise<MergeInfoAnswerLocationMap | null> {
    try {
      await this.repository.update(id, data);
      return await this.repository.findOne({ where: { id } });
    } catch (error) {
      this.logger.error(`Error updating merge info mapping ${id}: ${error.message}`, error.stack);
      handleKnownErrors(ERROR_CODES.MERGE_INFO_UPDATE_FAILED, error);
    }
  }

  /**
   * Soft delete a merge info mapping
   */
  async softDelete(id: number): Promise<void> {
    try {
      await this.repository.update(id, { isActive: false });
    } catch (error) {
      this.logger.error(
        `Error soft deleting merge info mapping ${id}: ${error.message}`,
        error.stack,
      );
      handleKnownErrors(ERROR_CODES.MERGE_INFO_DELETE_FAILED, error);
    }
  }

  /**
   * Bulk create merge info mappings
   */
  async bulkCreate(
    data: Partial<MergeInfoAnswerLocationMap>[],
  ): Promise<MergeInfoAnswerLocationMap[]> {
    try {
      const entities = this.repository.create(data);
      return await this.repository.save(entities);
    } catch (error) {
      this.logger.error(`Error bulk creating merge info mappings: ${error.message}`, error.stack);
      handleKnownErrors(ERROR_CODES.MERGE_INFO_CREATE_FAILED, error);
    }
  }

  /**
   * Get template with merge info mappings
   * Returns template object enriched with its merge field mappings
   */
  async getTemplateWithMergeInfo(
    template: any,
  ): Promise<any> {
    try {
      const mergeFieldMappings = await this.findByTemplateId(template.id);
      return {
        ...template,
        mergeFieldMappings,
      };
    } catch (error) {
      this.logger.error(
        `Error getting template with merge info: ${error.message}`,
        error.stack,
      );
      handleKnownErrors(ERROR_CODES.MERGE_INFO_NOT_FOUND, error);
    }
  }
}
