/**
 * Obligation Operations for DatabaseService
 *
 * Provides CRUD and query operations for the obligations table.
 * Obligations track contract deadlines, deliverables, and compliance items.
 *
 * @module database/obligation-operations
 */
import { v4 as uuidv4 } from 'uuid';
export const OBLIGATION_TYPES = [
    'payment',
    'delivery',
    'notification',
    'renewal',
    'termination',
    'compliance',
    'reporting',
    'approval',
    'other',
];
export const OBLIGATION_STATUSES = ['active', 'fulfilled', 'overdue', 'waived', 'expired'];
// =============================================================================
// CREATE
// =============================================================================
/**
 * Create a new obligation
 */
export function createObligation(db, params) {
    const id = uuidv4();
    const now = new Date().toISOString();
    db.prepare(`
    INSERT INTO obligations (id, document_id, extraction_id, obligation_type, description,
      responsible_party, due_date, recurring, status, source_chunk_id, source_page,
      confidence, created_at, metadata_json)
    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
  `).run(id, params.document_id, params.extraction_id ?? null, params.obligation_type, params.description, params.responsible_party ?? null, params.due_date ?? null, params.recurring ?? null, params.status ?? 'active', params.source_chunk_id ?? null, params.source_page ?? null, params.confidence ?? 1.0, now, params.metadata_json ?? '{}');
    return {
        id,
        document_id: params.document_id,
        extraction_id: params.extraction_id ?? null,
        obligation_type: params.obligation_type,
        description: params.description,
        responsible_party: params.responsible_party ?? null,
        due_date: params.due_date ?? null,
        recurring: params.recurring ?? null,
        status: params.status ?? 'active',
        source_chunk_id: params.source_chunk_id ?? null,
        source_page: params.source_page ?? null,
        confidence: params.confidence ?? 1.0,
        created_at: now,
        metadata_json: params.metadata_json ?? '{}',
    };
}
// =============================================================================
// LIST WITH FILTERS
// =============================================================================
/**
 * List obligations with optional filters
 */
export function listObligations(db, filters) {
    const conditions = [];
    const queryParams = [];
    if (filters.document_id) {
        conditions.push('o.document_id = ?');
        queryParams.push(filters.document_id);
    }
    if (filters.obligation_type) {
        conditions.push('o.obligation_type = ?');
        queryParams.push(filters.obligation_type);
    }
    if (filters.status) {
        conditions.push('o.status = ?');
        queryParams.push(filters.status);
    }
    if (filters.due_before) {
        conditions.push('o.due_date IS NOT NULL AND o.due_date <= ?');
        queryParams.push(filters.due_before);
    }
    if (filters.due_after) {
        conditions.push('o.due_date IS NOT NULL AND o.due_date >= ?');
        queryParams.push(filters.due_after);
    }
    if (filters.responsible_party) {
        conditions.push('o.responsible_party = ?');
        queryParams.push(filters.responsible_party);
    }
    const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
    const countRow = db
        .prepare(`SELECT COUNT(*) as cnt FROM obligations o ${whereClause}`)
        .get(...queryParams);
    const limit = filters.limit ?? 50;
    const offset = filters.offset ?? 0;
    const obligations = db
        .prepare(`
    SELECT o.* FROM obligations o
    ${whereClause}
    ORDER BY o.due_date ASC NULLS LAST, o.created_at DESC
    LIMIT ? OFFSET ?
  `)
        .all(...queryParams, limit, offset);
    return { obligations, total: countRow.cnt };
}
// =============================================================================
// UPDATE STATUS
// =============================================================================
/**
 * Update obligation status
 * @throws Error if obligation not found
 */
export function updateObligationStatus(db, id, status, reason) {
    const existing = db.prepare('SELECT * FROM obligations WHERE id = ?').get(id);
    if (!existing) {
        throw new Error(`Obligation not found: ${id}`);
    }
    // Update metadata with status change reason if provided
    let metadata = {};
    try {
        metadata = JSON.parse(existing.metadata_json || '{}');
    }
    catch (error) {
        const preview = (existing.metadata_json || '').substring(0, 200);
        throw new Error(`Corrupt metadata_json in obligation ${id}. Cannot update status without valid metadata. Raw value: "${preview}". Parse error: ${error instanceof Error ? error.message : String(error)}`);
    }
    if (reason) {
        const statusHistory = metadata.status_history ?? [];
        statusHistory.push({
            from: existing.status,
            to: status,
            reason,
            changed_at: new Date().toISOString(),
        });
        metadata.status_history = statusHistory;
    }
    db.prepare(`
    UPDATE obligations SET status = ?, metadata_json = ? WHERE id = ?
  `).run(status, JSON.stringify(metadata), id);
    return {
        ...existing,
        status,
        metadata_json: JSON.stringify(metadata),
    };
}
// =============================================================================
// CALENDAR VIEW
// =============================================================================
/**
 * Get obligations grouped by month for calendar view
 */
export function getObligationCalendar(db, options) {
    const monthsAhead = options.months_ahead ?? 3;
    const now = new Date();
    const endDate = new Date(now);
    endDate.setMonth(endDate.getMonth() + monthsAhead);
    const conditions = ['o.due_date IS NOT NULL', 'o.due_date >= ?', 'o.due_date <= ?'];
    const queryParams = [now.toISOString(), endDate.toISOString()];
    if (options.status) {
        conditions.push('o.status = ?');
        queryParams.push(options.status);
    }
    if (options.document_id) {
        conditions.push('o.document_id = ?');
        queryParams.push(options.document_id);
    }
    const whereClause = `WHERE ${conditions.join(' AND ')}`;
    const obligations = db
        .prepare(`
    SELECT o.* FROM obligations o
    ${whereClause}
    ORDER BY o.due_date ASC
  `)
        .all(...queryParams);
    // Group by month
    const monthMap = new Map();
    for (const ob of obligations) {
        if (!ob.due_date)
            continue;
        const month = ob.due_date.substring(0, 7); // YYYY-MM
        const existing = monthMap.get(month);
        if (existing) {
            existing.push(ob);
        }
        else {
            monthMap.set(month, [ob]);
        }
    }
    // Convert to sorted array
    const result = [];
    for (const [month, obs] of monthMap.entries()) {
        result.push({ month, obligations: obs });
    }
    result.sort((a, b) => a.month.localeCompare(b.month));
    return result;
}
// =============================================================================
// MARK OVERDUE
// =============================================================================
/**
 * Mark active obligations with past due dates as overdue
 * @returns Number of obligations marked overdue
 */
export function markOverdueObligations(db) {
    const result = db
        .prepare(`
    UPDATE obligations
    SET status = 'overdue'
    WHERE due_date < datetime('now')
      AND status = 'active'
      AND due_date IS NOT NULL
  `)
        .run();
    return result.changes;
}
//# sourceMappingURL=obligation-operations.js.map