'use strict';

import type { Db } from '../types/db';

// Canonical writers for a transaction's match state.
//
// A transaction's match state lives in three columns that must move together:
//   match_status   'unmatched' | 'matched' | 'ignored'
//   matched_bill_id  the bill when matched, else NULL
//   ignored          1 when explicitly ignored, else 0
//
// These were previously updated by copy-pasted inline UPDATEs across routes and
// services, which is exactly how they drift out of sync — e.g. QA-B5-04, where a
// bill purge left match_status='matched' with a NULL bill. Routing every
// single-transaction transition through these helpers keeps the columns
// consistent by construction. All are ownership-scoped (user_id) and return the
// number of rows changed. Bulk transitions (auto-match sweep, retention purge)
// stay in their own services where the WHERE clause is fundamentally different.

/**
 * Mark a transaction matched to a bill.
 * @param resetIgnored also clear the ignored flag (used when matching a
 *   transaction directly, which implicitly un-ignores it).
 */
function markMatched(
  db: Db,
  userId: number,
  transactionId: number,
  billId: number,
  { resetIgnored = false }: { resetIgnored?: boolean } = {},
): number {
  return db
    .prepare(
      `
    UPDATE transactions
    SET matched_bill_id = ?, match_status = 'matched'${resetIgnored ? ', ignored = 0' : ''}, updated_at = datetime('now')
    WHERE id = ? AND user_id = ?
  `,
    )
    .run(billId, transactionId, userId).changes;
}

/**
 * Clear a transaction's match — back to 'unmatched' with no bill.
 * @param resetIgnored also clear the ignored flag (un-ignore).
 */
function markUnmatched(
  db: Db,
  userId: number,
  transactionId: number,
  { resetIgnored = false }: { resetIgnored?: boolean } = {},
): number {
  return db
    .prepare(
      `
    UPDATE transactions
    SET matched_bill_id = NULL, match_status = 'unmatched'${resetIgnored ? ', ignored = 0' : ''}, updated_at = datetime('now')
    WHERE id = ? AND user_id = ?
  `,
    )
    .run(transactionId, userId).changes;
}

/** Mark a transaction ignored — dropped from matching, no bill. */
function markIgnored(db: Db, userId: number, transactionId: number): number {
  return db
    .prepare(
      `
    UPDATE transactions
    SET ignored = 1, match_status = 'ignored', matched_bill_id = NULL, updated_at = datetime('now')
    WHERE id = ? AND user_id = ?
  `,
    )
    .run(transactionId, userId).changes;
}

module.exports = { markMatched, markUnmatched, markIgnored };
