import { Router, Request, Response } from 'express';
import { prisma } from '../db/prisma';
import { requireAuth, requireRole } from '../middleware/auth';
import fs from 'fs';
import path from 'path';

const BLOCKED_USERNAMES_PATH = path.resolve(__dirname, '../../config/blocked-usernames.txt');

function getBlockedUsernames(): Set<string> {
  try {
    const content = fs.readFileSync(BLOCKED_USERNAMES_PATH, 'utf-8');
    return new Set(
      content
        .split('\n')
        .map((l) => l.trim().toLowerCase())
        .filter(Boolean)
    );
  } catch {
    return new Set();
  }
}

const USERNAME_REGEX = /^[a-z0-9._-]+$/i;

function validateUsername(
  username: string,
  opts?: { allowReserved?: boolean }
): string | null {
  if (!username || username.trim().length === 0) return 'Username is required';
  if (username.length > 50) return 'Username must be 50 characters or fewer';
  if (!USERNAME_REGEX.test(username)) return 'Username may only contain letters, numbers, dots, hyphens, and underscores';
  if (!opts?.allowReserved) {
    const blocked = getBlockedUsernames();
    if (blocked.has(username.toLowerCase())) return 'This username is reserved';
  }
  return null;
}

const router = Router();

router.get(
  '/',
  requireAuth,
  requireRole(['ADMIN']),
  async (_req: Request, res: Response) => {
    try {
      const users = await prisma.user.findMany({
        orderBy: { createdAt: 'desc' },
      });
      res.json(users);
    } catch (err) {
      console.error('List users error:', err);
      res.status(500).json({ error: 'Internal server error' });
    }
  }
);

router.post(
  '/promote',
  requireAuth,
  requireRole(['ADMIN']),
  async (req: Request, res: Response) => {
    try {
      const { pubkey } = req.body;
      if (!pubkey) {
        res.status(400).json({ error: 'pubkey is required' });
        return;
      }

      const user = await prisma.user.upsert({
        where: { pubkey },
        update: { role: 'MODERATOR' },
        create: { pubkey, role: 'MODERATOR' },
      });

      res.json(user);
    } catch (err) {
      console.error('Promote user error:', err);
      res.status(500).json({ error: 'Internal server error' });
    }
  }
);

router.post(
  '/demote',
  requireAuth,
  requireRole(['ADMIN']),
  async (req: Request, res: Response) => {
    try {
      const { pubkey } = req.body;
      if (!pubkey) {
        res.status(400).json({ error: 'pubkey is required' });
        return;
      }

      const user = await prisma.user.upsert({
        where: { pubkey },
        update: { role: 'USER' },
        create: { pubkey, role: 'USER' },
      });

      res.json(user);
    } catch (err) {
      console.error('Demote user error:', err);
      res.status(500).json({ error: 'Internal server error' });
    }
  }
);

router.get(
  '/me/username-check',
  requireAuth,
  async (req: Request, res: Response) => {
    try {
      const username = (req.query.username as string || '').trim().toLowerCase();
      const error = validateUsername(username);
      if (error) {
        res.json({ available: false, reason: error });
        return;
      }

      const existing = await prisma.user.findFirst({
        where: {
          username: { equals: username },
          NOT: { pubkey: req.user!.pubkey },
        },
      });

      if (existing) {
        res.json({ available: false, reason: 'Username is already taken' });
        return;
      }

      res.json({ available: true });
    } catch (err) {
      console.error('Username check error:', err);
      res.status(500).json({ error: 'Internal server error' });
    }
  }
);

router.patch(
  '/me',
  requireAuth,
  async (req: Request, res: Response) => {
    try {
      const { username } = req.body;
      const normalized = (username as string || '').trim().toLowerCase();

      const error = validateUsername(normalized);
      if (error) {
        res.status(400).json({ error });
        return;
      }

      const existing = await prisma.user.findFirst({
        where: {
          username: { equals: normalized },
          NOT: { pubkey: req.user!.pubkey },
        },
      });

      if (existing) {
        res.status(409).json({ error: 'Username is already taken' });
        return;
      }

      const user = await prisma.user.upsert({
        where: { pubkey: req.user!.pubkey },
        update: { username: normalized },
        create: { pubkey: req.user!.pubkey, username: normalized },
      });

      res.json(user);
    } catch (err) {
      console.error('Update profile error:', err);
      res.status(500).json({ error: 'Internal server error' });
    }
  }
);

router.patch(
  '/:pubkey',
  requireAuth,
  requireRole(['ADMIN']),
  async (req: Request, res: Response) => {
    try {
      const pubkeyRaw = req.params.pubkey;
      const pubkey =
        typeof pubkeyRaw === 'string' ? pubkeyRaw : Array.isArray(pubkeyRaw) ? pubkeyRaw[0] : '';
      if (!pubkey) {
        res.status(400).json({ error: 'pubkey is required' });
        return;
      }

      const { username } = req.body;
      const normalized = (username as string || '').trim().toLowerCase();

      const error = validateUsername(normalized, { allowReserved: true });
      if (error) {
        res.status(400).json({ error });
        return;
      }

      const target = await prisma.user.findUnique({ where: { pubkey } });
      if (!target) {
        res.status(404).json({ error: 'User not found' });
        return;
      }

      const existing = await prisma.user.findFirst({
        where: {
          username: { equals: normalized },
          NOT: { pubkey },
        },
      });

      if (existing) {
        res.status(409).json({ error: 'Username is already taken' });
        return;
      }

      const user = await prisma.user.update({
        where: { pubkey },
        data: { username: normalized },
      });

      res.json(user);
    } catch (err) {
      console.error('Admin update user username error:', err);
      res.status(500).json({ error: 'Internal server error' });
    }
  }
);

export default router;
