import express from 'express';
import mongoose from 'mongoose';
import dotenv from 'dotenv';
import jwt from 'jsonwebtoken';
import cors from 'cors';
import User, { IUser } from './models/User';
import ShopItem from './models/ShopItem';

dotenv.config();

// Расширяем типы Express
declare global {
  namespace Express {
    interface Request {
      user?: {
        userId: string;
        telegramId: string;
      }
    }
  }
}

const app = express();

// Middleware
app.use(cors({
  origin: process.env.NEXT_PUBLIC_URL || 'http://localhost:3000',
  credentials: true
}));
app.use(express.json());

// Подключение к MongoDB
mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost:27017/campfire-id')
  .then(() => console.log('Connected to MongoDB'))
  .catch(err => console.error('MongoDB connection error:', err));

// Middleware для проверки JWT
const authenticateToken = (req: express.Request, res: express.Response, next: express.NextFunction) => {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];

  if (!token) {
    return res.status(401).json({ error: 'Требуется авторизация' });
  }

  jwt.verify(token, process.env.JWT_SECRET || 'your-secret-key', (err: any, user: any) => {
    if (err) {
      return res.status(403).json({ error: 'Недействительный токен' });
    }
    req.user = user;
    next();
  });
};

// Обработка ошибок
const errorHandler = (err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
  console.error(err.stack);
  res.status(500).json({ 
    error: 'Ошибка сервера',
    message: process.env.NODE_ENV === 'development' ? err.message : undefined
  });
};

// Регистрация/авторизация пользователя
app.post('/api/auth', async (req, res, next) => {
  try {
    const { telegramId, username } = req.body;

    if (!telegramId || !username) {
      return res.status(400).json({ error: 'Отсутствуют обязательные поля' });
    }

    let user = await User.findOne({ telegramId });
    
    if (!user) {
      user = new User({
        telegramId,
        username,
        // Начальный бонус для новых пользователей
        balance: 100
      });
      await user.save();
    }

    const token = jwt.sign(
      { userId: user._id, telegramId },
      process.env.JWT_SECRET || 'your-secret-key',
      { expiresIn: '7d' }
    );

    res.json({ token, user });
  } catch (error) {
    next(error);
  }
});

// Получение профиля пользователя
app.get('/api/profile', authenticateToken, async (req, res) => {
  try {
    const user = await User.findById(req.user.userId);
    if (!user) {
      return res.status(404).json({ error: 'Пользователь не найден' });
    }
    res.json(user);
  } catch (error) {
    res.status(500).json({ error: 'Ошибка сервера' });
  }
});

// Получение списка предметов в магазине
app.get('/api/shop', authenticateToken, async (req, res) => {
  try {
    const items = await ShopItem.find({ available: true });
    res.json(items);
  } catch (error) {
    res.status(500).json({ error: 'Ошибка сервера' });
  }
});

// Покупка предмета
app.post('/api/shop/purchase', authenticateToken, async (req, res) => {
  try {
    const { itemId } = req.body;
    const user = await User.findById(req.user.userId);
    const item = await ShopItem.findById(itemId);

    if (!user || !item) {
      return res.status(404).json({ error: 'Пользователь или предмет не найден' });
    }

    if (user.balance < item.price) {
      return res.status(400).json({ error: 'Недостаточно средств' });
    }

    // Обновляем баланс и инвентарь
    user.balance -= item.price;
    const existingItem = user.inventory.find(i => i.itemId === itemId);
    
    if (existingItem) {
      existingItem.quantity += 1;
    } else {
      user.inventory.push({
        itemId: item._id,
        name: item.name,
        description: item.description,
        quantity: 1,
        imageUrl: item.imageUrl
      });
    }

    await user.save();
    res.json({ success: true, user });
  } catch (error) {
    res.status(500).json({ error: 'Ошибка сервера' });
  }
});

// Перевод баланса между пользователями
app.post('/api/transfer', authenticateToken, async (req, res) => {
  try {
    const { recipientUsername, amount } = req.body;
    
    if (amount <= 0) {
      return res.status(400).json({ error: 'Неверная сумма перевода' });
    }

    const sender = await User.findById(req.user.userId);
    const recipient = await User.findOne({ username: recipientUsername });

    if (!sender || !recipient) {
      return res.status(404).json({ error: 'Отправитель или получатель не найден' });
    }

    if (sender.balance < amount) {
      return res.status(400).json({ error: 'Недостаточно средств' });
    }

    // Выполняем перевод
    sender.balance -= amount;
    recipient.balance += amount;

    await sender.save();
    await recipient.save();

    // Добавляем достижение за первый перевод
    if (sender.achievements.every(a => a.id !== 'first_transfer')) {
      await sender.addAchievement({
        id: 'first_transfer',
        name: 'Щедрая душа',
        description: 'Совершили первый перевод',
        dateUnlocked: new Date()
      });
    }

    res.json({ success: true, balance: sender.balance });
  } catch (error) {
    res.status(500).json({ error: 'Ошибка сервера' });
  }
});

// Добавляем обработчик ошибок в конце
app.use(errorHandler);

const PORT = process.env.PORT || 3001;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
}); 