import { Router, Response } from 'express';
import { z } from 'zod';
import bcrypt from 'bcryptjs';
import db from '../db';
import { AuthRequest } from '../middleware/auth';

const router = Router();

const changePasswordSchema = z.object({
  currentPassword: z.string().min(1, 'Current password is required'),
  newPassword: z.string().min(8, 'Password must be at least 8 characters'),
});

const updateNotificationsSchema = z.object({
  emailEnabled: z.boolean().optional(),
  webhookUrl: z.string().url().optional().nullable(),
  webhookEnabled: z.boolean().optional(),
  slackWebhookUrl: z.string().url().optional().nullable(),
  slackEnabled: z.boolean().optional(),
});

// Get user settings
router.get('/', async (req: AuthRequest, res: Response): Promise<void> => {
  try {
    if (!req.user) {
      res.status(401).json({ error: 'unauthorized', message: 'Not authenticated' });
      return;
    }

    const user = await db.users.findById(req.user.userId);

    if (!user) {
      res.status(404).json({ error: 'not_found', message: 'User not found' });
      return;
    }

    // Return user settings (exclude password hash)
    res.json({
      settings: {
        email: user.email,
        plan: user.plan,
        stripeCustomerId: user.stripeCustomerId,
        emailEnabled: user.emailEnabled ?? true,
        webhookUrl: user.webhookUrl,
        webhookEnabled: user.webhookEnabled ?? false,
        slackWebhookUrl: user.slackWebhookUrl,
        slackEnabled: user.slackEnabled ?? false,
        createdAt: user.createdAt,
        lastLoginAt: user.lastLoginAt,
      },
    });
  } catch (error) {
    console.error('Get settings error:', error);
    res.status(500).json({ error: 'server_error', message: 'Failed to get settings' });
  }
});

// Change password
router.post('/change-password', async (req: AuthRequest, res: Response): Promise<void> => {
  try {
    if (!req.user) {
      res.status(401).json({ error: 'unauthorized', message: 'Not authenticated' });
      return;
    }

    const input = changePasswordSchema.parse(req.body);

    const user = await db.users.findById(req.user.userId);

    if (!user) {
      res.status(404).json({ error: 'not_found', message: 'User not found' });
      return;
    }

    // Verify current password
    const isValidPassword = await bcrypt.compare(input.currentPassword, user.passwordHash);

    if (!isValidPassword) {
      res.status(401).json({ error: 'invalid_password', message: 'Current password is incorrect' });
      return;
    }

    // Hash new password
    const newPasswordHash = await bcrypt.hash(input.newPassword, 10);

    // Update password
    await db.users.updatePassword(req.user.userId, newPasswordHash);

    res.json({ message: 'Password changed successfully' });
  } catch (error) {
    if (error instanceof z.ZodError) {
      res.status(400).json({
        error: 'validation_error',
        message: 'Invalid input',
        details: error.errors,
      });
      return;
    }

    console.error('Change password error:', error);
    res.status(500).json({ error: 'server_error', message: 'Failed to change password' });
  }
});

// Update notification preferences
router.put('/notifications', async (req: AuthRequest, res: Response): Promise<void> => {
  try {
    if (!req.user) {
      res.status(401).json({ error: 'unauthorized', message: 'Not authenticated' });
      return;
    }

    const input = updateNotificationsSchema.parse(req.body);

    await db.users.updateNotificationSettings(req.user.userId, {
      emailEnabled: input.emailEnabled,
      webhookUrl: input.webhookUrl,
      webhookEnabled: input.webhookEnabled,
      slackWebhookUrl: input.slackWebhookUrl,
      slackEnabled: input.slackEnabled,
    });

    res.json({ message: 'Notification settings updated successfully' });
  } catch (error) {
    if (error instanceof z.ZodError) {
      res.status(400).json({
        error: 'validation_error',
        message: 'Invalid input',
        details: error.errors,
      });
      return;
    }

    console.error('Update notifications error:', error);
    res.status(500).json({ error: 'server_error', message: 'Failed to update notifications' });
  }
});

// Delete account
router.delete('/account', async (req: AuthRequest, res: Response): Promise<void> => {
  try {
    if (!req.user) {
      res.status(401).json({ error: 'unauthorized', message: 'Not authenticated' });
      return;
    }

    const { password } = req.body;

    if (!password) {
      res.status(400).json({ error: 'validation_error', message: 'Password is required' });
      return;
    }

    const user = await db.users.findById(req.user.userId);

    if (!user) {
      res.status(404).json({ error: 'not_found', message: 'User not found' });
      return;
    }

    // Verify password before deletion
    const isValidPassword = await bcrypt.compare(password, user.passwordHash);

    if (!isValidPassword) {
      res.status(401).json({ error: 'invalid_password', message: 'Password is incorrect' });
      return;
    }

    // Delete all user's monitors (cascades to snapshots and alerts)
    const monitors = await db.monitors.findByUserId(req.user.userId);
    for (const monitor of monitors) {
      await db.monitors.delete(monitor.id);
    }

    // Delete user
    await db.users.delete(req.user.userId);

    res.json({ message: 'Account deleted successfully' });
  } catch (error) {
    console.error('Delete account error:', error);
    res.status(500).json({ error: 'server_error', message: 'Failed to delete account' });
  }
});

export default router;
