import { getDb } from "../config/db.js";
import { calculateTax } from "../services/tax.service.js";
import { roles, transactionStatus } from "../utils/constants.js";

export const listTransactions = async (req, res) => {
  const { role, notary_id } = req.user;
  const db = getDb();
  const privileged =
    role === roles.MINISTRY_FINANCE ||
    role === roles.MINISTRY_JUSTICE ||
    role === roles.SUPER_ADMIN;
  const [items] = await db.execute(
    `SELECT id, invoice_number, notary_id, type, asset_type, client_name, amount, tax_amount, total_amount,
            details, attachment_path, status, created_by, approved_by, created_at
     FROM transactions
     ${privileged ? "" : "WHERE notary_id = ?"}
     ORDER BY created_at DESC`,
    privileged ? [] : [notary_id]
  );
  res.json(items);
};

export const createTransaction = async (req, res) => {
  const db = getDb();
  const amount = Number(req.body.amount || 0);
  const tax_amount = calculateTax(req.body.type, req.body.asset_type, amount);
  const totalAmount = Number((amount + tax_amount).toFixed(2));
  const attachmentPath = req.file ? `/uploads/transactions/${req.file.filename}` : null;
  const [result] = await db.execute(
    `INSERT INTO transactions
     (notary_id, type, asset_type, client_name, amount, tax_amount, total_amount, details, attachment_path, status, created_by, invoice_number)
     VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
    [
      req.user.notary_id,
      req.body.type,
      req.body.asset_type,
      req.body.client_name,
      amount,
      tax_amount,
      totalAmount,
      JSON.stringify(req.body.details || {}),
      attachmentPath,
      transactionStatus.PENDING,
      req.user.id,
      'TEMP'
    ]
  );

  const invoiceNumber = `INV-${String(result.insertId).padStart(6, '0')}`;
  await db.execute(`UPDATE transactions SET invoice_number = ? WHERE id = ?`, [invoiceNumber, result.insertId]);

  res.status(201).json({
    id: result.insertId,
    notary_id: req.user.notary_id,
    type: req.body.type,
    asset_type: req.body.asset_type,
    client_name: req.body.client_name,
    amount,
    tax_amount,
    total_amount: totalAmount,
    details: req.body.details || {},
    status: transactionStatus.PENDING,
    created_by: req.user.id,
    approved_by: null
  });
};

export const markPaid = async (req, res) => {
  const db = getDb();
  const transactionId = Number(req.params.id);
  const [rows] = await db.execute(
    `SELECT id, total_amount FROM transactions WHERE id = ?`,
    [transactionId]
  );
  const transaction = rows[0];

  if (!transaction) {
    return res.status(404).json({ message: "Transaction not found" });
  }

  await db.execute(`UPDATE transactions SET status = ? WHERE id = ?`, [
    transactionStatus.PAID,
    transactionId
  ]);
  const [paymentResult] = await db.execute(
    `INSERT INTO payments (transaction_id, total, reference_number, phone)
     VALUES (?, ?, ?, ?)`,
    [
      transactionId,
      transaction.total_amount,
      req.body.reference_number || `REF-${transactionId}`,
      req.body.phone || ""
    ]
  );

  return res.json({
    transaction: { ...transaction, status: transactionStatus.PAID },
    payment: {
      id: paymentResult.insertId,
      transaction_id: transactionId,
      total: transaction.total_amount,
      reference_number: req.body.reference_number || `REF-${transactionId}`,
      phone: req.body.phone || ""
    }
  });
};

export const approveTransaction = async (req, res) => {
  const db = getDb();
  const transactionId = Number(req.params.id);
  const { status, rejection_note } = req.body;
  
  const [rows] = await db.execute(
    `SELECT id, status FROM transactions WHERE id = ?`,
    [transactionId]
  );
  const transaction = rows[0];

  if (!transaction) {
    return res.status(404).json({ message: "Transaction not found" });
  }

  let nextStatus;
  if (status === transactionStatus.REJECTED) {
    // Logic: If Executive rejects, status returns to 'returned' so Teller can edit
    nextStatus = transactionStatus.RETURNED;
  } else {
    nextStatus = transactionStatus.COMPLETED;
  }

  await db.execute(
    `UPDATE transactions SET status = ?, approved_by = ?, rejection_note = ? WHERE id = ?`,
    [nextStatus, req.user.id, rejection_note || null, transactionId]
  );

  return res.json({ id: transactionId, status: nextStatus, approved_by: req.user.id });
};

export const updateTransaction = async (req, res) => {
  const db = getDb();
  const transactionId = Number(req.params.id);
  const { role, notary_id } = req.user;

  // Check if transaction exists and if it can be edited
  const [rows] = await db.execute(
    `SELECT * FROM transactions WHERE id = ?`,
    [transactionId]
  );
  const transaction = rows[0];

  if (!transaction) {
    return res.status(404).json({ message: "Transaction not found" });
  }

  // Permission Check: Only Teller from the same notary can edit, 
  // and ONLY if status is 'returned'
  if (role !== roles.TELLER || transaction.notary_id !== notary_id) {
    return res.status(403).json({ message: "You do not have permission to edit this transaction" });
  }

  if (transaction.status !== transactionStatus.RETURNED) {
    return res.status(400).json({ message: "Only rejected transactions can be edited" });
  }

  const amount = Number(req.body.amount || transaction.amount);
  const tax_amount = calculateTax(req.body.type || transaction.type, req.body.asset_type || transaction.asset_type, amount);
  const totalAmount = Number((amount + tax_amount).toFixed(2));
  
  await db.execute(
    `UPDATE transactions 
     SET type = ?, asset_type = ?, client_name = ?, amount = ?, tax_amount = ?, total_amount = ?, details = ?, status = ?
     WHERE id = ?`,
    [
      req.body.type || transaction.type,
      req.body.asset_type || transaction.asset_type,
      req.body.client_name || transaction.client_name,
      amount,
      tax_amount,
      totalAmount,
      JSON.stringify(req.body.details || JSON.parse(transaction.details || '{}')),
      transactionStatus.PAID, // Once corrected, it goes back to 'paid' (ready for executive)
      transactionId
    ]
  );

  res.json({ success: true, message: "Transaction updated and resubmitted" });
};
