import { Router } from 'express';
import { OtpCode, User } from '../models/index.js';
import { requireAuth, signUserToken } from '../middleware/auth.js';
import { sendError } from '../util/httpError.js';

const router = Router();

const DEV_OTP = () => process.env.DEV_OTP || '123456';

router.post('/request-otp', async (req, res) => {
  const phone = String(req.body?.phone || '').trim();
  if (!/^\d{10,15}$/.test(phone)) {
    return sendError(res, 400, 'VALIDATION_ERROR', 'Invalid phone number');
  }
  const code = DEV_OTP();
  const expires = new Date(Date.now() + 10 * 60 * 1000);
  await OtpCode.create({ phone, code, expires_at: expires });
  return res.json({
    ok: true,
    message:
      process.env.NODE_ENV === 'production'
        ? 'OTP sent'
        : `OTP stored for dev (use code: ${code})`,
  });
});

router.post('/verify-otp', async (req, res) => {
  const phone = String(req.body?.phone || '').trim();
  const code = String(req.body?.code || '').trim();
  const name = String(req.body?.name || '').trim();
  if (!/^\d{10,15}$/.test(phone)) {
    return sendError(res, 400, 'VALIDATION_ERROR', 'Invalid phone number');
  }
  if (!code) {
    return sendError(res, 400, 'VALIDATION_ERROR', 'Code is required');
  }

  const row = await OtpCode.findOne({
    where: { phone },
    order: [['id', 'DESC']],
    raw: true,
  });
  const devMatch =
    process.env.NODE_ENV !== 'production' && code === DEV_OTP();
  const dbMatch =
    row &&
    row.code === code &&
    new Date(row.expires_at).getTime() > Date.now();
  if (!dbMatch && !devMatch) {
    return sendError(res, 400, 'VALIDATION_ERROR', 'Invalid or expired OTP');
  }

  let user = await User.findOne({ where: { phone } });
  if (!user) {
    const displayName = name || `Customer ${phone.slice(-4)}`;
    user = await User.create({
      name: displayName,
      phone,
      role: 'customer',
    });
  } else if (name && user.role === 'customer' && user.name !== name) {
    user.name = name;
    await user.save();
  }

  const token = signUserToken(user);
  return res.json({
    token,
    user: {
      id: Number(user.id),
      name: user.name,
      phone: user.phone,
      role: user.role,
    },
  });
});

/** Dev shortcut: returns JWT without OTP when NODE_ENV !== production */
router.post('/login', async (req, res) => {
  if (process.env.NODE_ENV === 'production') {
    return sendError(
      res,
      403,
      'FORBIDDEN',
      'Use /auth/request-otp and /auth/verify-otp in production'
    );
  }
  const phone = String(req.body?.phone || '').trim();
  if (!/^\d{10,15}$/.test(phone)) {
    return sendError(res, 400, 'VALIDATION_ERROR', 'Invalid phone number');
  }
  let user = await User.findOne({ where: { phone } });
  if (!user) {
    let role = 'customer';
    let name = `Test Customer`;
    
    if (phone === '9999999999') {
      role = 'super_admin';
      name = 'Super Admin (Dev)';
    } else if (phone === '8888888888') {
      role = 'admin';
      name = 'Admin (Dev)';
    } else if (phone === '7777777777') {
      role = 'employee';
      name = 'Employee (Dev)';
    }

    user = await User.create({
      name,
      phone,
      role,
    });
  }
  const token = signUserToken(user);
  return res.json({
    token,
    user: {
      id: Number(user.id),
      name: user.name,
      phone: user.phone,
      role: user.role,
    },
  });
});

router.get('/me', requireAuth, async (req, res) => {
  const user = await User.findByPk(req.user.id, { raw: true });
  if (!user) {
    return sendError(res, 404, 'NOT_FOUND', 'User not found');
  }
  return res.json({ user });
});

export default router;
