import { Router } from 'express';
import jwt from 'jsonwebtoken';
import { db, VALID_ROLES, initDiscordUsers } from '../db/init.js';
import { authenticateToken, requireRole } from '../middleware/auth.js';
import { getDiscordAuthUrl, exchangeCode, getDiscordUser, getGuildMember, getGuildMemberships, getUserRole, getUserRoleFromMemberships } from '../services/discord.js';

const router = Router();

// Initialize Discord users table
initDiscordUsers();

// ===== Guest Login =====

// Create guest token (view-only, expires in 24h)
router.post('/guest', (req, res) => {
  const guestId = 'guest_' + Date.now() + '_' + Math.random().toString(36).substring(2, 9);

  const token = jwt.sign(
    {
      id: guestId,
      username: 'Gast',
      role: 'guest',
      isGuest: true
    },
    process.env.JWT_SECRET,
    { expiresIn: '24h' }
  );

  res.json({ token });
});

// ===== Discord OAuth2 =====

// Start Discord OAuth2 flow
router.get('/discord', (req, res) => {
  res.redirect(getDiscordAuthUrl());
});

// Discord OAuth2 callback
router.get('/discord/callback', async (req, res) => {
  const { code, error } = req.query;

  // Redirect URL for frontend
  const frontendUrl = process.env.FRONTEND_URL || 'https://gsm.dimension47.de';

  if (error) {
    return res.redirect(`${frontendUrl}/login?error=discord_denied`);
  }

  if (!code) {
    return res.redirect(`${frontendUrl}/login?error=no_code`);
  }

  try {
    // Exchange code for access token
    const tokenData = await exchangeCode(code);

    // Get Discord user info
    const discordUser = await getDiscordUser(tokenData.access_token);

    // Check if user is in any of the configured guilds
    const memberships = await getGuildMemberships(discordUser.id);

    if (!memberships) {
      return res.redirect(`${frontendUrl}/login?error=not_in_guild`);
    }

    // Determine role based on Discord roles (highest role from all servers)
    const role = getUserRoleFromMemberships(memberships);

    // Use first membership for display name
    const member = memberships[0].member;

    // Get display name (nickname or username)
    const displayName = member.nick || discordUser.global_name || discordUser.username;

    // Upsert user in database
    const existingUser = db.prepare('SELECT * FROM discord_users WHERE discord_id = ?').get(discordUser.id);

    let userId;
    if (existingUser) {
      // Update existing user
      db.prepare(`
        UPDATE discord_users
        SET username = ?, discriminator = ?, avatar = ?, role = ?, updated_at = CURRENT_TIMESTAMP
        WHERE discord_id = ?
      `).run(displayName, discordUser.discriminator || '0', discordUser.avatar, role, discordUser.id);
      userId = existingUser.id;
    } else {
      // Create new user
      const result = db.prepare(`
        INSERT INTO discord_users (discord_id, username, discriminator, avatar, role)
        VALUES (?, ?, ?, ?, ?)
      `).run(discordUser.id, displayName, discordUser.discriminator || '0', discordUser.avatar, role);
      userId = result.lastInsertRowid;
    }

    // Create JWT token
    const token = jwt.sign(
      {
        id: userId,
        discordId: discordUser.id,
        username: displayName,
        role,
        avatar: discordUser.avatar
      },
      process.env.JWT_SECRET,
      { expiresIn: '7d' }
    );

    // Redirect to frontend with token
    res.redirect(`${frontendUrl}/auth/callback?token=${token}`);

  } catch (err) {
    console.error('Discord OAuth error:', err);
    res.redirect(`${frontendUrl}/login?error=oauth_failed`);
  }
});

// Get current user info
router.get('/me', authenticateToken, (req, res) => {
  // Check if it's a guest user
  if (req.user.isGuest) {
    return res.json({
      id: req.user.id,
      username: req.user.username,
      role: req.user.role,
      isGuest: true
    });
  }

  // Check if it's a Discord user
  if (req.user.discordId) {
    const user = db.prepare('SELECT id, discord_id, username, avatar, role FROM discord_users WHERE id = ?').get(req.user.id);
    if (!user) {
      return res.status(404).json({ error: 'User not found' });
    }
    return res.json({
      id: user.id,
      discordId: user.discord_id,
      username: user.username,
      avatar: user.avatar,
      role: user.role
    });
  }

  // Fallback for old users (shouldn't happen after migration)
  const user = db.prepare('SELECT id, username, role FROM users WHERE id = ?').get(req.user.id);
  if (!user) {
    return res.status(404).json({ error: 'User not found' });
  }
  res.json({ id: user.id, username: user.username, role: user.role });
});

// Refresh user role from Discord (useful if roles changed)
router.post('/refresh-role', authenticateToken, async (req, res) => {
  if (!req.user.discordId) {
    return res.status(400).json({ error: 'Not a Discord user' });
  }

  try {
    const memberships = await getGuildMemberships(req.user.discordId);

    if (!memberships) {
      return res.status(403).json({ error: 'No longer in any guild' });
    }

    const newRole = getUserRoleFromMemberships(memberships);

    db.prepare('UPDATE discord_users SET role = ?, updated_at = CURRENT_TIMESTAMP WHERE discord_id = ?')
      .run(newRole, req.user.discordId);

    // Generate new token with updated role
    const token = jwt.sign(
      {
        id: req.user.id,
        discordId: req.user.discordId,
        username: req.user.username,
        role: newRole,
        avatar: req.user.avatar
      },
      process.env.JWT_SECRET,
      { expiresIn: '7d' }
    );

    res.json({ token, role: newRole });
  } catch (err) {
    console.error('Failed to refresh role:', err);
    res.status(500).json({ error: 'Failed to refresh role' });
  }
});

// ===== User Management (superadmin only) =====

// Get all Discord users
router.get('/users', authenticateToken, requireRole('superadmin'), (req, res) => {
  const users = db.prepare(`
    SELECT id, discord_id, username, avatar, role, created_at, updated_at
    FROM discord_users
    ORDER BY created_at DESC
  `).all();
  res.json(users);
});

// Update user role (override Discord role)
router.patch('/users/:id/role', authenticateToken, requireRole('superadmin'), (req, res) => {
  const userId = parseInt(req.params.id);
  const { role } = req.body;

  if (!VALID_ROLES.includes(role)) {
    return res.status(400).json({ error: 'Invalid role' });
  }

  if (userId === req.user.id) {
    return res.status(400).json({ error: 'Cannot change your own role' });
  }

  const user = db.prepare('SELECT id FROM discord_users WHERE id = ?').get(userId);
  if (!user) {
    return res.status(404).json({ error: 'User not found' });
  }

  db.prepare('UPDATE discord_users SET role = ? WHERE id = ?').run(role, userId);
  res.json({ message: 'Role updated' });
});

// Delete user
router.delete('/users/:id', authenticateToken, requireRole('superadmin'), (req, res) => {
  const userId = parseInt(req.params.id);

  if (userId === req.user.id) {
    return res.status(400).json({ error: 'Cannot delete yourself' });
  }

  const user = db.prepare('SELECT id FROM discord_users WHERE id = ?').get(userId);
  if (!user) {
    return res.status(404).json({ error: 'User not found' });
  }

  db.prepare('DELETE FROM discord_users WHERE id = ?').run(userId);
  res.json({ message: 'User deleted' });
});

export default router;
