import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common'
import { InjectModel } from '@nestjs/mongoose'
import { Model, Types } from 'mongoose'
import { Matter, MatterDocument } from '../common/schemas'
import { CreateMatterDto } from './dto/create-matter.dto'
import { UpdateMatterDto } from './dto/update-matter.dto'

@Injectable()
export class MattersService {
  constructor(
    @InjectModel(Matter.name) private matterModel: Model<MatterDocument>,
  ) {}

  async create(dto: CreateMatterDto): Promise<MatterDocument> {
    const matterNumber = await this.generateMatterNumber()
    const matter = new this.matterModel({ ...dto, matterNumber, status: 'open', openedDate: new Date(), billedTotal: 0, unbilledTotal: 0 })
    return matter.save()
  }

  async findAll(filters: {
    clientFolderId?: string
    attorney?: string
    status?: string
    practiceArea?: string
    limit?: number
    offset?: number
  }): Promise<{ items: MatterDocument[]; total: number }> {
    const query: any = {}
    if (filters.clientFolderId) query.clientFolderId = new Types.ObjectId(filters.clientFolderId)
    if (filters.status) query.status = filters.status
    if (filters.practiceArea) query.practiceArea = filters.practiceArea
    if (filters.attorney) query.$or = [
      { responsibleAttorney: filters.attorney },
      { supervisingAttorney: filters.attorney },
    ]

    const [items, total] = await Promise.all([
      this.matterModel.find(query)
        .sort({ createdAt: -1 })
        .skip(filters.offset ?? 0)
        .limit(filters.limit ?? 50)
        .exec(),
      this.matterModel.countDocuments(query),
    ])
    return { items, total }
  }

  async findOne(id: string): Promise<MatterDocument> {
    const matter = await this.matterModel.findById(id).exec()
    if (!matter) throw new NotFoundException(`Matter ${id} not found`)
    return matter
  }

  async update(id: string, dto: UpdateMatterDto): Promise<MatterDocument> {
    const matter = await this.matterModel.findByIdAndUpdate(id, dto, { new: true }).exec()
    if (!matter) throw new NotFoundException(`Matter ${id} not found`)
    return matter as MatterDocument
  }

  async close(id: string, outcome: string): Promise<MatterDocument> {
    const matter = await this.findOne(id)
    if (matter.status === 'closed') throw new BadRequestException('Matter is already closed')
    return this.matterModel.findByIdAndUpdate(
      id,
      { status: 'closed', closedDate: new Date(), closedOutcome: outcome },
      { new: true },
    ).exec() as Promise<MatterDocument>
  }

  private async generateMatterNumber(): Promise<string> {
    const year = new Date().getFullYear()
    const count = await this.matterModel.countDocuments({
      matterNumber: new RegExp(`^M-${year}-`),
    })
    return `M-${year}-${String(count + 1).padStart(4, '0')}`
  }
}
