/**
 * DocumentClassifierService — Agent #3 in the hierarchy.
 *
 * Called by the Prompt Analyst BEFORE any routing decision.
 * Identifies document type, matter reference, practice area, and recommended
 * action so that all downstream agents receive pre-qualified, domain-scoped
 * requests rather than having to figure out what they are looking at.
 *
 * Communication rules:
 *   MAY be called by: Prompt Analyst only
 *   MAY NOT call: any other agent
 *   Returns: structured classification result, nothing else
 *
 * Single-shot Claude call — no agentic tool loop. Classification is a
 * deterministic reasoning task, not a multi-step retrieval task.
 */

import { Injectable, Logger } from '@nestjs/common'
import { InjectModel } from '@nestjs/mongoose'
import { Model } from 'mongoose'
import Anthropic from '@anthropic-ai/sdk'
import { ConfigService } from '@nestjs/config'
import { Matter, MatterDocument, ClientFolder, ClientFolderDocument } from '../common/schemas'

// ─── Types ────────────────────────────────────────────────────────────────────

export type DocumentType =
  | 'court_filing'          // คำร้อง, คำฟ้อง, คำพิพากษา, บันทึก
  | 'court_order'           // คำสั่ง, หมาย
  | 'immigration_form'      // TM.7, TM.8, TM.28, TM.30, TM.47, etc.
  | 'work_permit'           // WP.1, WP.10, บัตรอนุญาตทำงาน
  | 'land_title'            // chanote (NS4), NS3, NS3K, SK1, bai jong
  | 'corporate_doc'         // MOA, AOA, DBD registration, BOI approval
  | 'government_circular'   // ministry circulars, policy updates, notifications
  | 'contract'              // lease, sale, employment, service agreements
  | 'client_correspondence' // emails, letters, LINE messages from/to client
  | 'legal_opinion'         // counsel memo, legal advice letter
  | 'invoice_financial'     // invoices, receipts, tax documents
  | 'power_of_attorney'     // POA, proxy documents
  | 'identification'        // passport, ID card, house registration
  | 'evidence'              // exhibits, statements, affidavits
  | 'other'

export type RecommendedAction =
  | 'file_and_notify'   // routine — file to matter, notify attorney
  | 'escalate'          // needs immediate attorney attention
  | 'deadline_alert'    // contains deadline / response window
  | 'rule_change'       // government circular with policy change
  | 'client_action'     // client must do something
  | 'routine'           // standard filing, no special action

export interface ClassificationResult {
  documentType:      DocumentType
  documentSubtype?:  string          // e.g. "TM.7", "chanote", "court_summons"
  practiceArea?:     string          // immigration | corporate | property | civil_litigation | employment | family | tax
  matterReference?:  string          // matter number extracted from document (e.g. "TM.7", "BOI-24-001")
  clientReference?:  string          // client name or reference extracted
  language:          'th' | 'en' | 'bilingual' | 'unknown'
  confidence:        number          // 0.0 – 1.0
  recommendedAction: RecommendedAction
  summary:           string          // one-sentence description of what the document is
  flags:             string[]        // e.g. ["deadline:2024-12-31", "urgent", "response_required"]
  rawExtracted: {
    dates?:    string[]
    amounts?:  string[]
    parties?:  string[]
    caseRefs?: string[]
  }
}

// ─── System prompt ────────────────────────────────────────────────────────────

const SYSTEM_PROMPT = `You are the Document Classifier for GPS Legal, a Thai law firm. Your ONLY job is to identify and classify legal documents.

PRACTICE AREAS: immigration, corporate, property, civil_litigation, employment, family, tax

DOCUMENT TYPES AND SIGNALS:
- court_filing: คำร้อง, คำฟ้อง, ใบแจ้งความ, affidavit, petition, statement of claim
- court_order: คำสั่ง, หมาย, summons, injunction, judgment, คำพิพากษา
- immigration_form: TM.7 TM.8 TM.28 TM.30 TM.47, visa extension, re-entry permit, 90-day report
- work_permit: WP.1 WP.10, ใบอนุญาตทำงาน, work permit renewal/application
- land_title: โฉนด, NS4 NS3 NS3K SK1, chanote, ใบจอง, title deed, land certificate
- corporate_doc: หนังสือบริคณห์สนธิ, MOA, AOA, DBD certificate, BOI approval letter, company registration
- government_circular: หนังสือเวียน, ประกาศ, ระเบียบ, ministry notification, policy update
- contract: สัญญา, lease agreement, employment contract, service agreement, MOU
- client_correspondence: email, letter, LINE message to/from client
- legal_opinion: memorandum, legal advice, counsel letter
- invoice_financial: ใบแจ้งหนี้, receipt, tax invoice, ใบเสร็จ
- power_of_attorney: หนังสือมอบอำนาจ, proxy, POA
- identification: passport, บัตรประชาชน, house registration, ทะเบียนบ้าน
- evidence: exhibit, witness statement, declaration, affidavit
- other: anything that does not fit above

PRACTICE AREA SIGNALS:
- immigration: visas, TM forms, work permits, 90-day reports, re-entry
- corporate: company registration, BOI, DBD, shareholder matters, foreign business
- property: land titles, lease, sale/purchase, construction permits
- civil_litigation: court filings, judgments, enforcement, disputes
- employment: work permits, labour contracts, termination, severance
- family: divorce, custody, adoption, inheritance
- tax: revenue department, VAT, income tax, customs

RECOMMENDED ACTION:
- escalate: urgent deadlines < 7 days, court orders requiring immediate response, urgent client matters
- deadline_alert: document contains a response deadline or hearing date
- rule_change: government circular announcing policy/regulation change
- client_action: document requires client to act (sign, attend, provide documents)
- file_and_notify: routine document, file to matter and alert attorney
- routine: already processed / informational only

OUTPUT: You must respond ONLY with valid JSON matching the ClassificationResult schema. No other text.

JSON schema:
{
  "documentType": "<DocumentType>",
  "documentSubtype": "<optional specific form name>",
  "practiceArea": "<optional practice area>",
  "matterReference": "<optional matter number from document>",
  "clientReference": "<optional client name/reference>",
  "language": "th|en|bilingual|unknown",
  "confidence": <0.0-1.0>,
  "recommendedAction": "<RecommendedAction>",
  "summary": "<one sentence>",
  "flags": ["<flag1>", "<flag2>"],
  "rawExtracted": {
    "dates": ["<date1>"],
    "amounts": ["<amount1>"],
    "parties": ["<party1>"],
    "caseRefs": ["<ref1>"]
  }
}`

// ─── Service ──────────────────────────────────────────────────────────────────

@Injectable()
export class DocumentClassifierService {
  private readonly logger = new Logger(DocumentClassifierService.name)
  private readonly anthropic: Anthropic
  private readonly MODEL = 'claude-haiku-4-5-20251001'  // fast + cheap — classification only

  constructor(
    @InjectModel(Matter.name)       private matterModel: Model<MatterDocument>,
    @InjectModel(ClientFolder.name) private folderModel: Model<ClientFolderDocument>,
    private readonly config: ConfigService,
  ) {
    this.anthropic = new Anthropic({ apiKey: config.get<string>('ANTHROPIC_API_KEY') })
  }

  /**
   * Classify a document from its text content.
   * @param documentText  Raw text extracted from the document (may be Thai or English)
   * @param filename      Optional filename hint (e.g. "TM7_chen.pdf")
   */
  async classify(documentText: string, filename?: string): Promise<ClassificationResult> {
    const userContent = [
      filename ? `FILENAME: ${filename}` : '',
      '',
      'DOCUMENT CONTENT:',
      documentText.slice(0, 8000),  // cap to avoid token blowout on large docs
    ].filter(Boolean).join('\n')

    this.logger.debug(`Classifying document${filename ? ` (${filename})` : ''}, ${documentText.length} chars`)

    try {
      const response = await this.anthropic.messages.create({
        model:      this.MODEL,
        max_tokens: 1024,
        system:     SYSTEM_PROMPT,
        messages:   [{ role: 'user', content: userContent }],
      })

      const raw = response.content
        .filter(b => b.type === 'text')
        .map(b => (b as any).text)
        .join('')
        .trim()

      // Strip markdown code fences if Claude wraps JSON
      const jsonStr = raw.replace(/^```json\s*/i, '').replace(/```\s*$/, '').trim()
      const result = JSON.parse(jsonStr) as ClassificationResult

      this.logger.log(
        `Classified as ${result.documentType}${result.documentSubtype ? `/${result.documentSubtype}` : ''} ` +
        `(${result.practiceArea ?? 'unknown area'}, confidence ${result.confidence.toFixed(2)}) — ${result.summary}`
      )

      return result
    } catch (err: any) {
      this.logger.error('Document classification failed', err)
      // Return a safe fallback so the Prompt Analyst can still route
      return {
        documentType:      'other',
        language:          'unknown',
        confidence:        0,
        recommendedAction: 'file_and_notify',
        summary:           'Classification failed — manual review required',
        flags:             ['classification_error'],
        rawExtracted:      {},
      }
    }
  }

  /**
   * Convenience: classify then attempt to resolve matter/client references
   * against the database and augment the result.
   */
  async classifyAndResolve(
    documentText: string,
    filename?: string,
  ): Promise<ClassificationResult & { resolvedMatterId?: string; resolvedClientId?: string }> {
    const result = await this.classify(documentText, filename)

    let resolvedMatterId: string | undefined
    let resolvedClientId: string | undefined

    // Try to resolve matterReference against DB
    if (result.matterReference) {
      const matter = await this.matterModel
        .findOne({ matterNumber: { $regex: result.matterReference, $options: 'i' } })
        .select('_id clientFolderId')
        .lean() as any
      if (matter) {
        resolvedMatterId = matter._id.toString()
        resolvedClientId = matter.clientFolderId?.toString()
      }
    }

    // Try to resolve clientReference if matter didn't give us one
    if (!resolvedClientId && result.clientReference) {
      const folder = await this.folderModel
        .findOne({ displayName: { $regex: result.clientReference, $options: 'i' } })
        .select('_id')
        .lean() as any
      if (folder) resolvedClientId = folder._id.toString()
    }

    return { ...result, resolvedMatterId, resolvedClientId }
  }
}
