import { Injectable, NotFoundException } from '@nestjs/common'
import { InjectModel } from '@nestjs/mongoose'
import { Model } from 'mongoose'
import { Expense, ExpenseDocument } from '../common/schemas'
import { CreateExpenseDto } from './dto/create-expense.dto'

@Injectable()
export class ExpensesService {
  constructor(@InjectModel(Expense.name) private model: Model<ExpenseDocument>) {}

  create(dto: CreateExpenseDto) {
    return this.model.create({
      ...dto,
      expenseDate: new Date(dto.expenseDate),
      billable:    dto.billable    ?? true,
      vatIncluded: dto.vatIncluded ?? false,
      vatRate:     dto.vatRate     ?? 0,
      currency:    dto.currency    ?? 'THB',
      status:      'pending',
    })
  }

  findAll(filters: {
    clientFolderId?: string
    matterId?:       string
    status?:         string
    billable?:       string
    limit?:          number
    offset?:         number
  }) {
    const query: Record<string, unknown> = {}
    if (filters.clientFolderId) query.clientFolderId = filters.clientFolderId
    if (filters.matterId)       query.matterId       = filters.matterId
    if (filters.status)         query.status         = filters.status
    if (filters.billable !== undefined) query.billable = filters.billable === 'true'

    return this.model
      .find(query)
      .sort({ expenseDate: -1 })
      .skip(filters.offset ?? 0)
      .limit(filters.limit  ?? 100)
      .exec()
  }

  async findOne(id: string) {
    const doc = await this.model.findById(id).exec()
    if (!doc) throw new NotFoundException(`Expense ${id} not found`)
    return doc
  }

  async update(id: string, patch: Partial<CreateExpenseDto>) {
    const doc = await this.findOne(id)
    Object.assign(doc, patch)
    if (patch.expenseDate) doc.expenseDate = new Date(patch.expenseDate)
    return doc.save()
  }

  async markBilled(ids: string[], invoiceId: string) {
    await this.model.updateMany(
      { _id: { $in: ids } },
      { $set: { status: 'billed', invoiceId } },
    ).exec()
  }

  async markUnbilled(invoiceId: string) {
    await this.model.updateMany(
      { invoiceId },
      { $set: { status: 'pending' }, $unset: { invoiceId: '' } },
    ).exec()
  }

  async delete(id: string) {
    const doc = await this.findOne(id)
    await doc.deleteOne()
    return { deleted: true }
  }
}
