import { Router, Request, Response } from 'express';
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import { z } from 'zod';
import { PrismaClient } from '@prisma/client';
import { sendEmail } from '../services/email';

const router = Router();
const prisma = new PrismaClient();

const registerSchema = z.object({
  email: z.string().email(),
  password: z.string().min(8).max(72),
  name: z.string().min(2).max(50).optional()
});

const loginSchema = z.object({
  email: z.string().email(),
  password: z.string()
});

function signToken(user: { id: string; role: string; email: string }) {
  return jwt.sign(
    { sub: user.id, role: user.role, email: user.email },
    process.env.JWT_SECRET!,
    { expiresIn: '7d' }
  );
}

// POST /api/auth/register
router.post('/register', async (req: Request, res: Response) => {
  try {
    const body = registerSchema.parse(req.body);
    const existing = await prisma.user.findUnique({ where: { email: body.email } });
    if (existing) return res.status(409).json({ error: 'Email already in use' });

    const passwordHash = await bcrypt.hash(body.password, 12);
    const user = await prisma.user.create({
      data: { email: body.email, passwordHash, name: body.name }
    });

    // Send welcome email (non-blocking)
    sendEmail({
      to: user.email,
      subject: 'Welcome to TheKetoBay! 🥑',
      template: 'welcome',
      data: { name: user.name || 'Keto Friend' }
    }).catch(console.error);

    // Auto-capture as email lead
    await prisma.emailLead.upsert({
      where: { email: user.email },
      create: { email: user.email, name: user.name, userId: user.id, source: 'HOMEPAGE_HERO' },
      update: { userId: user.id }
    });

    const token = signToken({ id: user.id, role: user.role, email: user.email });
    res.status(201).json({
      token,
      user: { id: user.id, email: user.email, name: user.name, role: user.role }
    });
  } catch (err) {
    if (err instanceof z.ZodError) return res.status(400).json({ error: 'Validation error', details: err.errors });
    res.status(500).json({ error: 'Registration failed' });
  }
});

// POST /api/auth/login
router.post('/login', async (req: Request, res: Response) => {
  try {
    const body = loginSchema.parse(req.body);
    const user = await prisma.user.findUnique({ where: { email: body.email } });
    if (!user || !user.passwordHash) return res.status(401).json({ error: 'Invalid credentials' });

    const valid = await bcrypt.compare(body.password, user.passwordHash);
    if (!valid) return res.status(401).json({ error: 'Invalid credentials' });

    // Update streak
    const today = new Date().toISOString().split('T')[0];
    const lastActive = user.lastActiveDate?.toISOString().split('T')[0];
    let streak = user.streakCount;
    if (lastActive !== today) {
      const yesterday = new Date(Date.now() - 86400000).toISOString().split('T')[0];
      streak = lastActive === yesterday ? streak + 1 : 1;
      await prisma.user.update({
        where: { id: user.id },
        data: { streakCount: streak, lastActiveDate: new Date() }
      });
    }

    const token = signToken({ id: user.id, role: user.role, email: user.email });
    res.json({
      token,
      user: {
        id: user.id, email: user.email, name: user.name, role: user.role,
        subscriptionTier: user.subscriptionTier, streakCount: streak
      }
    });
  } catch (err) {
    if (err instanceof z.ZodError) return res.status(400).json({ error: 'Validation error', details: err.errors });
    res.status(500).json({ error: 'Login failed' });
  }
});

// POST /api/auth/forgot-password
router.post('/forgot-password', async (req: Request, res: Response) => {
  try {
    const { email } = z.object({ email: z.string().email() }).parse(req.body);
    const user = await prisma.user.findUnique({ where: { email } });

    // Always return success to prevent email enumeration
    if (user) {
      const resetToken = jwt.sign({ sub: user.id, type: 'reset' }, process.env.JWT_SECRET!, { expiresIn: '1h' });
      await sendEmail({
        to: email,
        subject: 'Reset your TheKetoBay password',
        template: 'password-reset',
        data: { resetUrl: `${process.env.FRONTEND_URL}/reset-password?token=${resetToken}` }
      });
    }

    res.json({ message: 'If that email exists, a reset link has been sent.' });
  } catch {
    res.status(500).json({ error: 'Failed to process request' });
  }
});

// POST /api/auth/reset-password
router.post('/reset-password', async (req: Request, res: Response) => {
  try {
    const { token, password } = z.object({
      token: z.string(),
      password: z.string().min(8).max(72)
    }).parse(req.body);

    const payload = jwt.verify(token, process.env.JWT_SECRET!) as any;
    if (payload.type !== 'reset') return res.status(400).json({ error: 'Invalid token' });

    const passwordHash = await bcrypt.hash(password, 12);
    await prisma.user.update({ where: { id: payload.sub }, data: { passwordHash } });

    res.json({ message: 'Password updated successfully' });
  } catch {
    res.status(400).json({ error: 'Invalid or expired reset token' });
  }
});

// GET /api/auth/me
router.get('/me', async (req: Request, res: Response) => {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) return res.status(401).json({ error: 'Not authenticated' });

  try {
    const payload = jwt.verify(token, process.env.JWT_SECRET!) as any;
    const user = await prisma.user.findUnique({
      where: { id: payload.sub },
      select: {
        id: true, email: true, name: true, avatarUrl: true, role: true,
        subscriptionTier: true, subscriptionStatus: true, subscriptionEndsAt: true,
        streakCount: true, totalPoints: true, weightKg: true, targetWeightKg: true
      }
    });
    if (!user) return res.status(404).json({ error: 'User not found' });
    res.json({ user });
  } catch {
    res.status(401).json({ error: 'Invalid token' });
  }
});

export { router as authRouter };
