import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common'
import { InjectModel } from '@nestjs/mongoose'
import { Model } from 'mongoose'
import { ConflictCheck, ConflictCheckDocument, ClientFolder, ClientFolderDocument } from '../common/schemas'
import { CreateConflictCheckDto } from './dto/create-conflict-check.dto'
import { ClientFoldersService } from '../client-folders/client-folders.service'

@Injectable()
export class ConflictChecksService {
  constructor(
    @InjectModel(ConflictCheck.name) private checkModel: Model<ConflictCheckDocument>,
    @InjectModel(ClientFolder.name) private folderModel: Model<ClientFolderDocument>,
    private readonly foldersService: ClientFoldersService,
  ) {}

  async run(dto: CreateConflictCheckDto): Promise<ConflictCheckDocument> {
    const folder = await this.folderModel.findById(dto.clientFolderId).exec()
    if (!folder) throw new NotFoundException(`Client folder ${dto.clientFolderId} not found`)

    const hits = await this.foldersService.searchForConflicts(dto.searchTerms)
    const conflicts = hits.filter(h => String(h._id) !== String(folder._id))

    const result = conflicts.length > 0 ? 'conflict_found' : 'clear'

    const checkNumber = `CC-${Date.now()}`
    const check = new this.checkModel({
      checkNumber,
      clientFolderId: folder._id,
      requestedBy: 'system',
      requestDate: new Date(),
      searchTerms: dto.searchTerms,
      hits: conflicts.map(c => ({
        folderId: String(c._id),
        folderNumber: c.folderNumber,
        displayName: c.displayName,
        relationship: 'name_match',
        details: `Matched on search terms`,
      })),
      result,
    })
    const saved = await check.save()

    // Advance folder to conflict_check status if still a prospect
    if (folder.status === 'prospect') {
      await this.folderModel.findByIdAndUpdate(dto.clientFolderId, { status: 'conflict_check' }).exec()
    }

    return saved
  }

  async findForFolder(clientFolderId: string): Promise<ConflictCheckDocument[]> {
    return this.checkModel.find({ clientFolderId }).sort({ requestDate: -1 }).exec()
  }

  async findOne(id: string): Promise<ConflictCheckDocument> {
    const check = await this.checkModel.findById(id).exec()
    if (!check) throw new NotFoundException(`Conflict check ${id} not found`)
    return check
  }

  async waive(id: string, waiverRef: string, reviewedBy: string): Promise<ConflictCheckDocument> {
    const check = await this.findOne(id)
    if (check.result !== 'conflict_found') {
      throw new BadRequestException('Can only waive a check with conflict_found result')
    }
    return this.checkModel.findByIdAndUpdate(
      id,
      { result: 'waived', waiverRef, reviewedBy, reviewDate: new Date() },
      { new: true },
    ).exec() as Promise<ConflictCheckDocument>
  }
}
