import { Injectable } from '@nestjs/common'
import { InjectModel } from '@nestjs/mongoose'
import { Model } from 'mongoose'
import {
  ClientFolder, ClientFolderDocument,
  Matter, MatterDocument,
  Email, EmailDocument,
  Hearing, HearingDocument,
  Invoice, InvoiceDocument,
} from '../common/schemas'

@Injectable()
export class AgentToolsService {
  constructor(
    @InjectModel(ClientFolder.name) private folderModel:  Model<ClientFolderDocument>,
    @InjectModel(Matter.name)       private matterModel:  Model<MatterDocument>,
    @InjectModel(Email.name)        private emailModel:   Model<EmailDocument>,
    @InjectModel(Hearing.name)      private hearingModel: Model<HearingDocument>,
    @InjectModel(Invoice.name)      private invoiceModel: Model<InvoiceDocument>,
  ) {}

  // ── Tool implementations ──────────────────────────────────────────────────

  async searchClients(query: string) {
    return this.folderModel.find({
      $or: [
        { displayName: { $regex: query, $options: 'i' } },
        { folderNumber: { $regex: query, $options: 'i' } },
      ],
    }).select('_id displayName folderNumber status billingConfig.currency').limit(10).lean()
  }

  async getClientContext(clientFolderId: string) {
    const [folder, matters, recentEmails] = await Promise.all([
      this.folderModel.findById(clientFolderId).lean(),
      this.matterModel
        .find({ clientFolderId })
        .select('_id matterNumber title status practiceArea openedAt closedAt')
        .sort({ openedAt: -1 })
        .lean(),
      this.emailModel
        .find({ clientFolderId })
        .sort({ receivedAt: -1 })
        .limit(5)
        .select('subject from direction receivedAt isRead associationStatus')
        .lean(),
    ])
    return { folder, matters, recentEmails }
  }

  async listOpenMatters() {
    return this.matterModel
      .find({ status: { $in: ['active', 'in_progress', 'open'] } })
      .select('_id matterNumber title status practiceArea clientFolderId openedAt')
      .sort({ openedAt: -1 })
      .limit(50)
      .lean()
  }

  async listPendingEmails(limit = 20) {
    return this.emailModel
      .find({ associationStatus: 'pending_review' })
      .sort({ receivedAt: -1 })
      .limit(limit)
      .select('_id subject from to direction receivedAt associationStatus associationCandidates')
      .lean()
  }

  async associateEmail(
    emailId: string,
    clientFolderId: string,
    matterId: string | undefined,
    confirmedBy = 'prompt_analyst',
  ) {
    return this.emailModel.findByIdAndUpdate(
      emailId,
      {
        $set: {
          clientFolderId,
          matterId,
          associationStatus: 'confirmed',
          associationConfirmedBy: confirmedBy,
          associationConfirmedAt: new Date(),
        },
      },
      { new: true },
    ).lean()
  }

  async getCalendar(days = 14) {
    const from = new Date()
    const to   = new Date(Date.now() + days * 24 * 60 * 60 * 1000)
    return this.hearingModel
      .find({ hearingDate: { $gte: from, $lte: to } })
      .sort({ hearingDate: 1 })
      .select('hearingDate court caseNumber matterId clientFolderId hearingType notes')
      .lean()
  }

  async getOverdueInvoices() {
    const now = new Date()
    return this.invoiceModel
      .find({ status: { $in: ['sent', 'overdue'] }, dueDate: { $lt: now } })
      .select('_id invoiceNumber clientFolderId total currency dueDate status')
      .sort({ dueDate: 1 })
      .limit(20)
      .lean()
  }

  // ── Tool schema definitions (Anthropic SDK format) ─────────────────────────

  getToolDefinitions() {
    return [
      {
        name: 'search_clients',
        description: 'Search for client folders by name or folder number. Returns a list of matching clients with their IDs.',
        input_schema: {
          type: 'object' as const,
          properties: {
            query: { type: 'string', description: 'Name or folder number to search for' },
          },
          required: ['query'],
        },
      },
      {
        name: 'get_client_context',
        description: 'Get full context for a specific client: folder details, all matters, and recent emails. Use this before discussing any client-specific matter.',
        input_schema: {
          type: 'object' as const,
          properties: {
            clientFolderId: { type: 'string', description: 'The MongoDB _id of the client folder' },
          },
          required: ['clientFolderId'],
        },
      },
      {
        name: 'list_open_matters',
        description: 'List all currently active/open matters across all clients, with their reference numbers, practice areas, and status.',
        input_schema: {
          type: 'object' as const,
          properties: {},
          required: [],
        },
      },
      {
        name: 'list_pending_emails',
        description: 'List inbound emails that have not yet been routed to a client or matter. These need attorney attention to confirm routing.',
        input_schema: {
          type: 'object' as const,
          properties: {
            limit: { type: 'number', description: 'Max number to return (default 20)' },
          },
          required: [],
        },
      },
      {
        name: 'associate_email',
        description: 'Confirm routing of an email to a specific client folder and optionally a matter. Use this when the correct routing is clear.',
        input_schema: {
          type: 'object' as const,
          properties: {
            emailId:        { type: 'string', description: 'The _id of the email to route' },
            clientFolderId: { type: 'string', description: 'The client folder _id to route to' },
            matterId:       { type: 'string', description: 'Optional: the matter _id to link' },
          },
          required: ['emailId', 'clientFolderId'],
        },
      },
      {
        name: 'get_calendar',
        description: 'Get upcoming hearings and court dates within the next N days.',
        input_schema: {
          type: 'object' as const,
          properties: {
            days: { type: 'number', description: 'Look-ahead window in days (default 14)' },
          },
          required: [],
        },
      },
      {
        name: 'get_overdue_invoices',
        description: 'List invoices that are past their due date and unpaid. Use for billing briefings.',
        input_schema: {
          type: 'object' as const,
          properties: {},
          required: [],
        },
      },
    ]
  }

  // ── Dispatch ──────────────────────────────────────────────────────────────

  async execute(toolName: string, input: any): Promise<any> {
    switch (toolName) {
      case 'search_clients':       return this.searchClients(input.query)
      case 'get_client_context':   return this.getClientContext(input.clientFolderId)
      case 'list_open_matters':    return this.listOpenMatters()
      case 'list_pending_emails':  return this.listPendingEmails(input.limit)
      case 'associate_email':      return this.associateEmail(input.emailId, input.clientFolderId, input.matterId)
      case 'get_calendar':         return this.getCalendar(input.days)
      case 'get_overdue_invoices': return this.getOverdueInvoices()
      default: return { error: `Unknown tool: ${toolName}` }
    }
  }
}
