'use strict';
const express = require('express');
const { db, getSetting, productById } = require('../db');
const { sendMail, orderEmailHtml } = require('../lib/mail');
const { payfastParams } = require('../lib/payments');

const router = express.Router();

function money(n) {
  return 'R ' + Number(n || 0).toLocaleString('en-ZA', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}

router.get('/products', (req, res) => {
  const q = String(req.query.q || '').trim();
  let rows;
  if (q) {
    const like = `%${q}%`;
    rows = db.prepare('SELECT * FROM products WHERE name LIKE ? OR sku LIKE ? ORDER BY id').all(like, like);
  } else {
    rows = db.prepare('SELECT * FROM products ORDER BY id').all();
  }
  res.json(rows);
});

router.post('/contact', (req, res) => {
  const { name, email, phone, subject, body } = req.body;
  if (!name || !email || !body) return res.status(400).json({ error: 'Please fill in your name, email and message.' });
  const info = db
    .prepare('INSERT INTO messages (name, email, phone, subject, body) VALUES (?, ?, ?, ?, ?)')
    .run(String(name).trim(), String(email).trim(), String(phone || '').trim(), String(subject || '').trim(), String(body).trim());
  sendMail({
    to: getSetting('email', 'wasup1606@gmail.com'),
    subject: `New contact message from ${name}`,
    text: `From: ${name} <${email}> ${phone ? '| ' + phone : ''}\nSubject: ${subject}\n\n${body}`,
  });
  res.json({ ok: true, id: info.lastInsertRowid });
});

router.get('/order-status', (req, res) => {
  const number = String(req.query.number || '').trim();
  if (!number) return res.json({ ok: true, fulfilled: false });
  const order = db.prepare('SELECT status, review_requested FROM orders WHERE order_number = ?').get(number);
  const fulfilled = order ? (order.status === 'fulfilled' || order.status === 'completed') : false;
  res.json({ ok: true, fulfilled });
});

router.post('/coupons/validate', (req, res) => {
  const code = String(req.body.code || '').trim().toUpperCase();
  const subtotal = Number(req.body.subtotal || 0);
  const coupon = db.prepare('SELECT * FROM coupons WHERE UPPER(code) = ?').get(code);
  if (!coupon || !coupon.active) return res.json({ valid: false, error: 'Invalid discount code.' });
  if (coupon.expires_at && new Date(coupon.expires_at + 'Z') < new Date()) {
    return res.json({ valid: false, error: 'This discount code has expired.' });
  }
  if (coupon.usage_limit > 0 && coupon.used_count >= coupon.usage_limit) {
    return res.json({ valid: false, error: 'This discount code has reached its usage limit.' });
  }
  if (subtotal < coupon.min_subtotal) {
    return res.json({
      valid: false,
      error: `Minimum spend of ${money(coupon.min_subtotal)} required for this code.`,
    });
  }
  const discount =
    coupon.type === 'percent' ? (subtotal * coupon.value) / 100 : Math.min(coupon.value, subtotal);
  res.json({
    valid: true,
    code: coupon.code,
    discount: Math.round(discount * 100) / 100,
    type: coupon.type,
  });
});

router.post('/reviews', (req, res) => {
  const { name, city, title, body, rating, product_id } = req.body;
  if (!name || !body) return res.status(400).json({ error: 'Please add your name and a review.' });
  const cleanRating = Math.min(5, Math.max(1, Math.round(Number(rating) || 5)));
  const info = db
    .prepare('INSERT INTO reviews (product_id, name, city, title, body, rating, approved) VALUES (?, ?, ?, ?, ?, ?, 0)')
    .run(
      product_id ? Number(product_id) : null,
      String(name).trim(),
      String(city || '').trim(),
      String(title || '').trim(),
      String(body).trim(),
      cleanRating
    );
  sendMail({
    to: getSetting('email', 'wasup1606@gmail.com'),
    subject: 'New customer review submitted',
    text: `${name} (${city || 'no city'}) rated ${cleanRating}/5\nTitle: ${title || '—'}\n\n${body}\n\nApprove or delete it in Admin → Reviews.`,
  });
  res.json({ ok: true, id: info.lastInsertRowid });
});

router.post('/checkout', (req, res) => {
  const { items, customer, shipping, couponCode, paymentMethod, notes } = req.body;

  if (!Array.isArray(items) || items.length === 0) {
    return res.status(400).json({ error: 'Your cart is empty.' });
  }
  if (!customer || !customer.name || !customer.email || !customer.phone) {
    return res.status(400).json({ error: 'Please fill in your contact details.' });
  }
  if (!shipping || !shipping.line1 || !shipping.city) {
    return res.status(400).json({ error: 'Please fill in your delivery address.' });
  }
  if (!['payfast', 'cod'].includes(paymentMethod)) {
    return res.status(400).json({ error: 'Select a valid payment method.' });
  }

  const lineItems = [];
  let subtotal = 0;
  for (const it of items) {
    const p = productById(Number(it.id));
    if (!p || p.status !== 'live' || p.price == null || p.price <= 0) {
      return res.status(400).json({ error: `"${p ? p.name : 'item'}" is not available to purchase yet.` });
    }
    const qty = Math.max(1, Math.min(99, parseInt(it.qty, 10) || 1));
    if (p.stock < qty) {
      return res.status(400).json({ error: `Only ${p.stock} left in stock for "${p.name}".` });
    }
    let size = String(it.size || '').trim();
    const validSizes = String(p.sizes || '').split(/[\s,]+/).map((s) => s.trim()).filter(Boolean);
    if (p.size_type !== 'none' && validSizes.length) {
      if (!size) {
        return res.status(400).json({ error: `Please select a size for "${p.name}".` });
      }
      if (!validSizes.includes(size)) {
        return res.status(400).json({ error: `Size ${size} is not available for "${p.name}".` });
      }
    } else {
      size = '';
    }
    const price = Math.round(p.price * 100) / 100;
    lineItems.push({ product_id: p.id, name: p.name, price, qty, image: p.image, stock: p.stock, size });
    subtotal += price * qty;
  }
  subtotal = Math.round(subtotal * 100) / 100;

  let discountAmount = 0;
  let couponUsed = '';
  let couponId = null;
  if (couponCode) {
    const coupon = db.prepare('SELECT * FROM coupons WHERE UPPER(code) = ?').get(String(couponCode).trim().toUpperCase());
    const valid =
      coupon &&
      coupon.active &&
      !(coupon.expires_at && new Date(coupon.expires_at + 'Z') < new Date()) &&
      !(coupon.usage_limit > 0 && coupon.used_count >= coupon.usage_limit) &&
      subtotal >= coupon.min_subtotal;
    if (!valid) return res.status(400).json({ error: 'That discount code is not valid.' });
    discountAmount =
      coupon.type === 'percent' ? (subtotal * coupon.value) / 100 : Math.min(coupon.value, subtotal);
    discountAmount = Math.round(discountAmount * 100) / 100;
    couponUsed = coupon.code;
    couponId = coupon.id;
  }

  const freeThreshold = Number(getSetting('free_shipping_threshold', '500'));
  const baseFee = Number(getSetting('shipping_fee', '79'));
  const afterDiscount = subtotal - discountAmount;
  const shippingFee = afterDiscount >= freeThreshold ? 0 : baseFee;
  const total = Math.round((afterDiscount + shippingFee) * 100) / 100;

  let orderNumber;
  do {
    orderNumber = 'TC-' + Date.now().toString().slice(-6) + Math.floor(1000 + Math.random() * 9000);
  } while (db.prepare('SELECT 1 FROM orders WHERE order_number = ?').get(orderNumber));

  const payStatus = paymentMethod === 'cod' ? 'unpaid' : 'unpaid';
  const orderStatus = paymentMethod === 'cod' ? 'confirmed' : 'pending';

  const info = db
    .prepare(
      `INSERT INTO orders
       (order_number, user_id, email, name, phone, address_line1, address_line2, city, province, postal_code, country,
        subtotal, discount_amount, coupon_code, shipping_fee, total, currency, status, payment_method, payment_status, notes)
       VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
    )
    .run(
      orderNumber,
      req.user ? req.user.id : null,
      String(customer.email).trim(),
      String(customer.name).trim(),
      String(customer.phone).trim(),
      String(shipping.line1).trim(),
      String(shipping.line2 || '').trim(),
      String(shipping.city).trim(),
      String(shipping.province || '').trim(),
      String(shipping.postal || '').trim(),
      String(shipping.country || 'South Africa').trim(),
      subtotal,
      discountAmount,
      couponUsed,
      shippingFee,
      total,
      getSetting('currency', 'ZAR'),
      orderStatus,
      paymentMethod,
      payStatus,
      String(notes || '').trim()
    );

  const orderId = info.lastInsertRowid;
  const itemStmt = db.prepare('INSERT INTO order_items (order_id, product_id, name, price, qty, image, size) VALUES (?, ?, ?, ?, ?, ?, ?)');
  const stockStmt = db.prepare('UPDATE products SET stock = stock - ?, updated_at = datetime(\'now\') WHERE id = ?');
  for (const li of lineItems) {
    itemStmt.run(orderId, li.product_id, li.name, li.price, li.qty, li.image, li.size || '');
    stockStmt.run(li.qty, li.product_id);
  }
  if (couponId) {
    db.prepare('UPDATE coupons SET used_count = used_count + 1 WHERE id = ?').run(couponId);
  }

  const order = db.prepare('SELECT * FROM orders WHERE id = ?').get(orderId);
  sendMail({
    to: order.email,
    subject: `Order ${orderNumber} received — TOUS CINO`,
    html: orderEmailHtml(order, lineItems),
  });
  sendMail({
    to: getSetting('email', 'wasup1606@gmail.com'),
    subject: `New order ${orderNumber} — TOUS CINO`,
    text: `New order ${orderNumber} for ${money(total)} from ${order.name} (${order.email}).`,
  });

  let payment = null;
  if (paymentMethod === 'payfast') {
    payment = payfastParams(order, lineItems);
  }

  res.json({
    ok: true,
    order_number: orderNumber,
    total: money(total),
    payment_method: paymentMethod,
    payment,
  });
});

module.exports = router;
