import { BaseRepository } from "@edr/api-common";
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";

import { FileUploadField } from "./entities/file-upload-field.entity";
import { FileUploadSetting } from "./entities/file-upload-setting.entity";
import type { IFileUploadSettingsRepository } from "./interfaces/file-upload-settings.repository.interface";

@Injectable()
export class FileUploadSettingsRepository
  extends BaseRepository<FileUploadSetting>
  implements IFileUploadSettingsRepository
{
  constructor(
    @InjectRepository(FileUploadSetting)
    repository: Repository<FileUploadSetting>,
    @InjectRepository(FileUploadField)
    private readonly fieldsRepository: Repository<FileUploadField>,
  ) {
    super(repository);
  }

  /** Look up all settings for a given entity (e.g. "customer", "booking"). */
  findByEntity(entity: string): Promise<FileUploadSetting[]> {
    return this.repository.find({
      where: { entity },
      order: { label: "ASC" },
      relations: { fields: true },
    });
  }

  /** Look up a setting by its stable code. */
  findByCode(code: string): Promise<FileUploadSetting | null> {
    return this.repository.findOne({
      where: { code },
      relations: { fields: true },
    });
  }

  override findAll(): Promise<FileUploadSetting[]> {
    return this.repository.find({
      order: { label: "ASC" },
      relations: { fields: true },
    });
  }

  /** Replace the whole field list for a setting. Returns the saved rows. */
  async replaceFields(
    settingId: string,
    fields: Array<Partial<FileUploadField>>,
  ): Promise<FileUploadField[]> {
    await this.fieldsRepository.delete({ settingId });
    if (fields.length === 0) return [];
    const entities = fields.map((f, idx) =>
      this.fieldsRepository.create({
        ...f,
        settingId,
        displayOrder: f.displayOrder ?? idx + 1,
      }),
    );
    return this.fieldsRepository.save(entities);
  }

  async addField(
    settingId: string,
    field: Partial<FileUploadField>,
  ): Promise<FileUploadField> {
    const entity = this.fieldsRepository.create({ ...field, settingId });
    return this.fieldsRepository.save(entity);
  }

  async updateField(
    fieldId: string,
    data: Partial<FileUploadField>,
  ): Promise<FileUploadField | null> {
    await this.fieldsRepository.update(fieldId, data as never);
    return this.fieldsRepository.findOne({ where: { id: fieldId } });
  }

  async removeField(fieldId: string): Promise<void> {
    await this.fieldsRepository.softDelete(fieldId);
  }
}
