/**
 * Paynow Payment Gateway Integration
 * For Zimbabwe payments (Ecocash, Visa, etc.)
 */

const express = require('express');
const router = express.Router();
const path = require('path');
const Database = require('better-sqlite3');
const { v4: uuidv4 } = require('uuid');
const crypto = require('crypto');

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

// Auth middleware
const auth = (req, res, next) => {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) return res.status(401).json({ error: 'No token provided' });
  try {
    req.user = require('jsonwebtoken').verify(token, process.env.JWT_SECRET || 'africa-alert-secret-key-2024');
    next();
  } catch (err) {
    res.status(401).json({ error: 'Invalid token' });
  }
};

// Paynow configuration
const PAYNOW_INTEGRATION_ID = process.env.PAYNOW_INTEGRATION_ID || '';
const PAYNOW_INTEGRATION_KEY = process.env.PAYNOW_INTEGRATION_KEY || '';
const PAYNOW_RETURN_URL = process.env.PAYNOW_RETURN_URL || 'http://localhost:3000/fees';
const PAYNOW_BLOCKING_URL = process.env.PAYNOW_BLOCKING_URL || 'http://localhost:3000/api/payments/webhook';
const PAYNOW_API_URL = 'https://www.paynow.co.zw/interface/initiatetransaction';

// Helper to generate hash
const generateHash = (params, integrationKey) => {
  const sorted = Object.keys(params)
    .filter(k => params[k] !== null && params[k] !== undefined && params[k] !== '')
    .sort()
    .map(k => `${k}${params[k]}`)
    .join('');
  
  return crypto.createHash('sha1').update(sorted + integrationKey).digest('hex');
};

// ============ INITIATE PAYMENT ============

router.post('/initiate', auth, async (req, res) => {
  const { student_fee_id, amount, reference } = req.body;
  
  // Validate amount
  if (!amount || amount <= 0) {
    return res.status(400).json({ error: 'Invalid amount' });
  }
  
  // Get student fee record
  const studentFee = db.prepare(`
    SELECT sf.*, u.first_name, u.last_name, u.email,
      fg.name as fee_name
    FROM student_fees sf
    JOIN users u ON sf.student_id = u.id
    JOIN fee_groups fg ON sf.fee_group_id = fg.id
    WHERE sf.id = ?
  `).get(student_fee_id);
  
  if (!studentFee) {
    return res.status(404).json({ error: 'Student fee record not found' });
  }
  
  // Check if already paid
  if (studentFee.status === 'paid') {
    return res.status(400).json({ error: 'Fee already fully paid' });
  }
  
  // Check remaining amount
  const remaining = studentFee.amount - studentFee.paid_amount;
  if (amount > remaining) {
    amount = remaining; // Cap at remaining amount
  }
  
  // Generate reference
  const paymentReference = reference || `FEE-${studentFee.id}-${Date.now()}`;
  const uid = uuidv4();
  
  // Create pending payment record
  db.prepare(`
    INSERT INTO payments (uid, student_fee_id, amount, payment_method, reference_number, collected_by, status)
    VALUES (?, ?, ?, 'paynow', ?, ?, 'pending')
  `).run(uid, student_fee_id, amount, paymentReference, req.user.id);
  
  // If Paynow is configured, create Paynow transaction
  if (PAYNOW_INTEGRATION_ID && PAYNOW_INTEGRATION_KEY) {
    try {
      // Prepare Paynow parameters
      const paynowParams = {
        integrationid: PAYNOW_INTEGRATION_ID,
        returnurl: PAYNOW_RETURN_URL,
        blockingurl: PAYNOW_BLOCKING_URL,
        reference: paymentReference,
        amount: amount.toFixed(2),
        additionalinfo: `School Fee Payment - ${studentFee.fee_name}`,
        email: studentFee.email || '',
      };
      
      // Generate hash
      paynowParams.hash = generateHash(paynowParams, PAYNOW_INTEGRATION_KEY);
      
      // In production, would make HTTP request to Paynow
      // For now, return a mock response for testing
      const pollUrl = `https://www.paynow.co.zw/poll/${paymentReference}`;
      
      db.prepare(`
        UPDATE payments SET paynow_poll_url = ? WHERE uid = ?
      `).run(pollUrl, uid);
      
      res.json({
        success: true,
        payment_id: uid,
        reference: paymentReference,
        amount: amount,
        // In production, this would be the Paynow payment URL
        // payment_url: paynowResponse.url,
        payment_url: `${PAYNOW_API_URL}?reference=${paymentReference}&amount=${amount}`,
        poll_url: pollUrl,
        instructions: 'Redirect to Paynow to complete payment'
      });
      
    } catch (error) {
      console.error('Paynow initiation error:', error);
      res.status(500).json({ error: 'Failed to initiate payment' });
    }
  } else {
    // Paynow not configured - return mock response for testing
    res.json({
      success: true,
      payment_id: uid,
      reference: paymentReference,
      amount: amount,
      payment_url: `/mock-payment?ref=${paymentReference}&amount=${amount}`,
      poll_url: null,
      mode: 'test',
      instructions: 'Paynow not configured. Use test mode for development.'
    });
  }
});

// ============ CHECK PAYMENT STATUS ============

router.get('/status/:paymentId', auth, async (req, res) => {
  const { paymentId } = req.params;
  
  const payment = db.prepare(`
    SELECT p.*, sf.student_id, u.first_name, u.last_name, fg.name as fee_name
    FROM payments p
    JOIN student_fees sf ON p.student_fee_id = sf.id
    JOIN users u ON sf.student_id = u.id
    JOIN fee_groups fg ON sf.fee_group_id = fg.id
    WHERE p.uid = ?
  `).get(paymentId);
  
  if (!payment) {
    return res.status(404).json({ error: 'Payment not found' });
  }
  
  // Check with Paynow if configured
  if (payment.paynow_poll_url && PAYNOW_INTEGRATION_ID && PAYNOW_INTEGRATION_KEY) {
    try {
      // Poll Paynow for status
      const pollParams = {
        reference: payment.reference_number,
        hash: generateHash({ reference: payment.reference_number }, PAYNOW_INTEGRATION_KEY)
      };
      
      // In production, would make HTTP request to Paynow
      // For now, return local status
      res.json({
        payment_id: payment.uid,
        reference: payment.reference_number,
        amount: payment.amount,
        status: payment.status,
        student: `${payment.first_name} ${payment.last_name}`,
        fee_name: payment.fee_name,
        created_at: payment.created_at,
        paid_at: payment.paid_at
      });
      
    } catch (error) {
      console.error('Paynow poll error:', error);
      res.status(500).json({ error: 'Failed to check payment status' });
    }
  } else {
    // Return local status
    res.json({
      payment_id: payment.uid,
      reference: payment.reference_number,
      amount: payment.amount,
      status: payment.status,
      student: `${payment.first_name} ${payment.last_name}`,
      fee_name: payment.fee_name,
      created_at: payment.created_at,
      paid_at: payment.paid_at
    });
  }
});

// ============ PAYNOW WEBHOOK ============

router.post('/webhook', async (req, res) => {
  try {
    const { status, reference, pollurl } = req.body;
    
    console.log('Paynow webhook received:', { status, reference });
    
    if (!reference) {
      return res.status(400).json({ error: 'Missing reference' });
    }
    
    // Find payment by reference
    const payment = db.prepare(`
      SELECT p.*, sf.student_id, sf.fee_group_id, sf.amount as total_amount, sf.paid_amount
      FROM payments p
      JOIN student_fees sf ON p.student_fee_id = sf.id
      WHERE p.reference_number = ?
    `).get(reference);
    
    if (!payment) {
      console.log('Payment not found for reference:', reference);
      return res.status(404).json({ error: 'Payment not found' });
    }
    
    // Process based on status
    if (status === 'Paid' || status === 'Awaiting') {
      // IDEMPOTENCY CHECK: skip if already completed
      if (payment.status === 'completed') {
        console.log(`Payment already completed: ${reference}`);
        return res.json({ status: 'ok', note: 'already processed' });
      }

      // Update payment status
      db.prepare(`
        UPDATE payments SET 
          status = 'completed',
          paid_at = CURRENT_TIMESTAMP,
          updated_at = CURRENT_TIMESTAMP,
          sync_status = 'pending'
        WHERE uid = ?
      `).run(payment.uid);
      
      // Update student fee
      const newPaidAmount = payment.paid_amount + payment.amount;
      const isFullyPaid = newPaidAmount >= payment.total_amount;
      
      db.prepare(`
        UPDATE student_fees SET
          paid_amount = ?,
          status = ?,
          paid_at = ?,
          updated_at = CURRENT_TIMESTAMP,
          sync_status = 'pending'
        WHERE id = ?
      `).run(
        newPaidAmount,
        isFullyPaid ? 'paid' : 'partial',
        isFullyPaid ? new Date().toISOString() : null,
        payment.student_fee_id
      );
      
      console.log(`Payment confirmed: ${reference}, Amount: ${payment.amount}`);
      
    } else if (status === 'Cancelled' || status === 'Failed') {
      db.prepare(`
        UPDATE payments SET 
          status = 'failed',
          updated_at = CURRENT_TIMESTAMP
        WHERE uid = ?
      `).run(payment.uid);
      
      console.log(`Payment failed: ${reference}`);
    }
    
    res.json({ status: 'ok' });
    
  } catch (error) {
    console.error('Webhook processing error:', error);
    res.status(500).json({ error: 'Webhook processing failed' });
  }
});

// ============ GET PAYMENTS FOR STUDENT ============

router.get('/student/:studentId', auth, (req, res) => {
  const studentId = req.params.studentId;
  
  // Check permission - only admin, the student themselves, or their parent
  if (req.user.role !== 'admin' && req.user.id !== parseInt(studentId) && req.user.role !== 'parent') {
    // For parent, need to check if they're related to this student
    // Simplified: allow parents to see any student for now
  }
  
  const payments = db.prepare(`
    SELECT p.*, fg.name as fee_name, sf.amount as fee_amount
    FROM payments p
    JOIN student_fees sf ON p.student_fee_id = sf.id
    JOIN fee_groups fg ON sf.fee_group_id = fg.id
    WHERE sf.student_id = ?
    ORDER BY p.created_at DESC
  `).all(studentId);
  
  res.json(payments);
});

// ============ CANCEL PENDING PAYMENT ============

router.delete('/:paymentId', auth, (req, res) => {
  const { paymentId } = req.params;
  
  const payment = db.prepare('SELECT * FROM payments WHERE uid = ?').get(paymentId);
  
  if (!payment) {
    return res.status(404).json({ error: 'Payment not found' });
  }
  
  // Only cancel pending payments
  if (payment.status !== 'pending') {
    return res.status(400).json({ error: 'Can only cancel pending payments' });
  }
  
  db.prepare(`
    UPDATE payments SET status = 'cancelled', updated_at = CURRENT_TIMESTAMP
    WHERE uid = ?
  `).run(paymentId);
  
  res.json({ success: true });
});

module.exports = router;