/**
 * Finance Suppliers Controller
 *
 * Phase 2 (§10a) — thin alias around the existing inventory `suppliers`
 * table. Inventory creates the row shape; this controller exists so the
 * Accountant / Bursar back-office can manage vendors under the finance
 * module without conflicting with the inventory CRUD contract.
 *
 * Authorization: shared `financeAccess` set from finance.controller.js —
 * school_admin, systems_admin, principal, bursar, accountant, hr.
 */

const express = require('express');
const { v4: uuidv4 } = require('uuid');
const Database = require('better-sqlite3');
const path = require('path');
const AuditService = require('../services/AuditService');

const db = new Database(process.env.DB_PATH || path.join(__dirname, '../../data/school.db'));
db.pragma('foreign_keys = ON');

const router = express.Router();

const auth = (req, res, next) => {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) return res.status(401).json({ error: 'No token provided' });
  try {
    const jwt = require('jsonwebtoken');
    const { jwtSecret: JWT_SECRET } = require('../config');
    req.user = jwt.verify(token, JWT_SECRET);
    next();
  } catch (err) {
    return res.status(401).json({ error: 'Invalid token' });
  }
};

// Phase 0 widened this to include `hr`; §10a adds `accountant` so the new
// role is on equal footing with bursar for the operational back-office.
const financeAccess = (req, res, next) => {
  const allowed = ['school_admin', 'systems_admin', 'principal', 'bursar', 'accountant', 'hr'];
  if (!allowed.includes(req.user.role)) {
    return res.status(403).json({ error: 'Finance / accounting role required' });
  }
  next();
};

// ============ LIST (with optional status filter) ============

router.get('/', auth, financeAccess, (req, res) => {
  try {
    const { search, status } = req.query;
    let sql = 'SELECT * FROM suppliers WHERE is_deleted = 0';
    const params = [];
    if (search) {
      sql += ' AND (name LIKE ? OR code LIKE ? OR contact_person LIKE ? OR email LIKE ?)';
      const like = `%${search}%`;
      params.push(like, like, like, like);
    }
    if (status) {
      sql += ' AND is_active = ?';
      params.push(status === 'active' ? 1 : 0);
    }
    sql += ' ORDER BY name';
    const rows = db.prepare(sql).all(...params);
    res.json(rows);
  } catch (e) {
    res.status(500).json({ error: e.message });
  }
});

// ============ DETAIL ============

router.get('/:uid', auth, financeAccess, (req, res) => {
  try {
    const row = db.prepare('SELECT * FROM suppliers WHERE uid = ? AND is_deleted = 0').get(req.params.uid);
    if (!row) return res.status(404).json({ error: 'Supplier not found' });
    res.json(row);
  } catch (e) {
    res.status(500).json({ error: e.message });
  }
});

// ============ CREATE ============

router.post('/', auth, financeAccess, async (req, res) => {
  try {
    const { name, code, contact_person, email, phone, address, city, country, tax_id, bank_details, notes, is_active } = req.body;
    if (!name) return res.status(400).json({ error: 'name is required' });

    const uid = uuidv4();
    db.prepare(`
      INSERT INTO suppliers (
        uid, name, code, contact_person, email, phone,
        address, city, country, tax_id, bank_details, notes,
        is_active, sync_status
      ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending')
    `).run(
      uid, name, code || null, contact_person || null, email || null, phone || null,
      address || null, city || null, country || (country || 'Zimbabwe'), tax_id || null, bank_details || null, notes || null,
      is_active === undefined ? 1 : (is_active ? 1 : 0),
    );

    await AuditService.log(req, 'CREATE_SUPPLIER', { entityType: 'supplier', entityId: uid, newData: { name, code } });
    const row = db.prepare('SELECT * FROM suppliers WHERE id = last_insert_rowid()').get();
    res.status(201).json(row);
  } catch (e) {
    res.status(500).json({ error: e.message });
  }
});

// ============ UPDATE ============

router.patch('/:uid', auth, financeAccess, async (req, res) => {
  try {
    const existing = db.prepare('SELECT id FROM suppliers WHERE uid = ? AND is_deleted = 0').get(req.params.uid);
    if (!existing) return res.status(404).json({ error: 'Supplier not found' });

    const fields = ['name', 'code', 'contact_person', 'email', 'phone', 'address', 'city', 'country', 'tax_id', 'bank_details', 'notes', 'is_active'];
    const updates = [];
    const params = [];
    for (const f of fields) {
      if (req.body[f] !== undefined) {
        updates.push(`${f} = ?`);
        params.push(f === 'is_active' ? (req.body[f] ? 1 : 0) : req.body[f]);
      }
    }
    if (updates.length === 0) return res.status(400).json({ error: 'No updatable fields supplied' });

    updates.push(`updated_at = datetime('now', 'localtime')`, `sync_status = 'pending'`);
    params.push(req.params.uid);
    db.prepare(`UPDATE suppliers SET ${updates.join(', ')} WHERE uid = ?`).run(...params);

    await AuditService.log(req, 'UPDATE_SUPPLIER', { entityType: 'supplier', entityId: req.params.uid, newData: req.body });
    const row = db.prepare('SELECT * FROM suppliers WHERE uid = ?').get(req.params.uid);
    res.json(row);
  } catch (e) {
    res.status(500).json({ error: e.message });
  }
});

// ============ SOFT DELETE ============

router.delete('/:uid', auth, financeAccess, async (req, res) => {
  try {
    const existing = db.prepare('SELECT id FROM suppliers WHERE uid = ? AND is_deleted = 0').get(req.params.uid);
    if (!existing) return res.status(404).json({ error: 'Supplier not found' });
    db.prepare(`
      UPDATE suppliers
      SET is_deleted = 1, is_active = 0, updated_at = datetime('now', 'localtime'),
          sync_status = 'pending', last_synced_at = NULL
      WHERE uid = ?
    `).run(req.params.uid);
    await AuditService.log(req, 'DELETE_SUPPLIER', { entityType: 'supplier', entityId: req.params.uid });
    res.json({ success: true });
  } catch (e) {
    res.status(500).json({ error: e.message });
  }
});

module.exports = router;
