import type { Express } from "express";
import { createServer, type Server } from "http";
import { storage } from "./storage";
import { setupAuth, isAuthenticated } from "./simpleAuth";
import { insertArticleSchema, insertMediaOutletRequestSchema, insertBidSchema, insertCommentSchema, insertPredictionBetSchema } from "@shared/schema";

export async function registerRoutes(app: Express): Promise<Server> {
  // Auth middleware
  await setupAuth(app);

  // Auth routes
  app.get('/api/auth/user', isAuthenticated, async (req: any, res) => {
    try {
      const user = req.user;
      res.json(user);
    } catch (error) {
      console.error("Error fetching user:", error);
      res.status(500).json({ message: "Failed to fetch user" });
    }
  });

  // Media outlet routes
  app.get('/api/media-outlets', async (req, res) => {
    try {
      const category = req.query.category as string;
      const outlets = await storage.getMediaOutlets(category);
      res.json(outlets);
    } catch (error) {
      console.error("Error fetching media outlets:", error);
      res.status(500).json({ message: "Failed to fetch media outlets" });
    }
  });

  app.get('/api/media-outlets/:slug', async (req, res) => {
    try {
      const outlet = await storage.getMediaOutletBySlug(req.params.slug);
      if (!outlet) {
        return res.status(404).json({ message: "Media outlet not found" });
      }
      res.json(outlet);
    } catch (error) {
      console.error("Error fetching media outlet:", error);
      res.status(500).json({ message: "Failed to fetch media outlet" });
    }
  });

  // Article routes
  app.get('/api/media-outlets/:outletId/articles', async (req, res) => {
    try {
      const articles = await storage.getArticlesByOutlet(req.params.outletId);
      res.json(articles);
    } catch (error) {
      console.error("Error fetching articles:", error);
      res.status(500).json({ message: "Failed to fetch articles" });
    }
  });

  app.get('/api/media-outlets/:slug/articles', async (req, res) => {
    try {
      const outlet = await storage.getMediaOutletBySlug(req.params.slug);
      if (!outlet) {
        return res.status(404).json({ message: "Media outlet not found" });
      }
      const articles = await storage.getArticlesByOutlet(outlet.id);
      res.json(articles);
    } catch (error) {
      console.error("Error fetching articles by slug:", error);
      res.status(500).json({ message: "Failed to fetch articles" });
    }
  });

  app.get('/api/articles/:slug', async (req, res) => {
    try {
      const article = await storage.getArticleBySlug(req.params.slug);
      if (!article) {
        return res.status(404).json({ message: "Article not found" });
      }
      res.json(article);
    } catch (error) {
      console.error("Error fetching article:", error);
      res.status(500).json({ message: "Failed to fetch article" });
    }
  });

  app.get('/api/articles/:slug/markets', async (req, res) => {
    try {
      const article = await storage.getArticleBySlug(req.params.slug);
      if (!article) {
        return res.status(404).json({ message: "Article not found" });
      }
      const markets = await storage.getPredictionMarkets(article.id);
      res.json(markets);
    } catch (error) {
      console.error("Error fetching prediction markets for article:", error);
      res.status(500).json({ message: "Failed to fetch prediction markets" });
    }
  });

  app.get('/api/articles/featured', async (req, res) => {
    try {
      const limit = parseInt(req.query.limit as string) || 10;
      const articles = await storage.getFeaturedArticles(limit);
      res.json(articles);
    } catch (error) {
      console.error("Error fetching featured articles:", error);
      res.status(500).json({ message: "Failed to fetch featured articles" });
    }
  });

  app.post('/api/articles', isAuthenticated, async (req: any, res) => {
    try {
      const user = req.user;
      
      if (!user || (user.role !== 'admin' && user.role !== 'superadmin')) {
        return res.status(403).json({ message: "Insufficient permissions" });
      }

      const articleData = insertArticleSchema.parse({
        ...req.body,
        authorId: user.id
      });
      
      const article = await storage.createArticle(articleData);
      res.status(201).json(article);
    } catch (error) {
      console.error("Error creating article:", error);
      res.status(500).json({ message: "Failed to create article" });
    }
  });

  // Prediction market routes
  app.get('/api/prediction-markets', async (req, res) => {
    try {
      const articleId = req.query.articleId as string;
      const markets = await storage.getPredictionMarkets(articleId);
      res.json(markets);
    } catch (error) {
      console.error("Error fetching prediction markets:", error);
      res.status(500).json({ message: "Failed to fetch prediction markets" });
    }
  });

  // Auction routes
  app.get('/api/auctions', async (req, res) => {
    try {
      const auctions = await storage.getActiveAuctions();
      res.json(auctions);
    } catch (error) {
      console.error("Error fetching auctions:", error);
      res.status(500).json({ message: "Failed to fetch auctions" });
    }
  });

  app.get('/api/media-outlets/:slug/auction', async (req, res) => {
    try {
      const outlet = await storage.getMediaOutletBySlug(req.params.slug);
      if (!outlet) {
        return res.status(404).json({ message: "Media outlet not found" });
      }
      const auction = await storage.getAuctionByMediaOutlet(outlet.id);
      res.json(auction || null);
    } catch (error) {
      console.error("Error fetching auction:", error);
      res.status(500).json({ message: "Failed to fetch auction" });
    }
  });

  app.get('/api/auctions/:id/bids', async (req, res) => {
    try {
      const bids = await storage.getBidsByAuctionId(req.params.id);
      res.json(bids);
    } catch (error) {
      console.error("Error fetching bids:", error);
      res.status(500).json({ message: "Failed to fetch bids" });
    }
  });

  app.post('/api/auctions/:id/bid', isAuthenticated, async (req: any, res) => {
    try {
      const userId = req.user.claims?.sub || req.user.id;
      const bidData = insertBidSchema.parse({
        ...req.body,
        auctionId: req.params.id,
        bidderId: userId
      });
      
      const bid = await storage.placeBid(bidData);
      res.status(201).json(bid);
    } catch (error) {
      console.error("Error placing bid:", error);
      res.status(500).json({ message: "Failed to place bid" });
    }
  });

  app.post('/api/media-outlets/:slug/auction/bids', isAuthenticated, async (req: any, res) => {
    try {
      const outlet = await storage.getMediaOutletBySlug(req.params.slug);
      if (!outlet) {
        return res.status(404).json({ message: "Media outlet not found" });
      }
      
      const auction = await storage.getAuctionByMediaOutlet(outlet.id);
      if (!auction) {
        return res.status(404).json({ message: "No active auction found for this media outlet" });
      }

      const userId = req.user.claims?.sub || req.user.id;
      const bidData = insertBidSchema.parse({
        ...req.body,
        auctionId: auction.id,
        bidderId: userId
      });
      
      const bid = await storage.placeBid(bidData);
      res.status(201).json(bid);
    } catch (error) {
      console.error("Error placing bid:", error);
      res.status(500).json({ message: "Failed to place bid" });
    }
  });

  // Prediction market betting endpoints
  app.post('/api/prediction-markets/:marketId/bets', isAuthenticated, async (req: any, res) => {
    try {
      const userId = req.user.claims?.sub || req.user.id;
      const { side, amount } = req.body;

      // Validate request
      if (!side || !amount || !["yes", "no"].includes(side)) {
        return res.status(400).json({ message: "Invalid bet data" });
      }

      if (parseFloat(amount) <= 0) {
        return res.status(400).json({ message: "Bet amount must be positive" });
      }

      const betData = insertPredictionBetSchema.parse({
        marketId: req.params.marketId,
        userId,
        side,
        amount: amount.toString()
      });
      
      const bet = await storage.createPredictionBet(betData);
      res.status(201).json(bet);
    } catch (error) {
      console.error("Error placing prediction bet:", error);
      if (error.message === "Prediction market not found") {
        return res.status(404).json({ message: "Prediction market not found" });
      }
      res.status(500).json({ message: "Failed to place bet" });
    }
  });

  // Media outlet request routes
  app.get('/api/media-outlet-requests', isAuthenticated, async (req: any, res) => {
    try {
      const userId = req.user.claims?.sub || req.user.id;
      const user = await storage.getUser(userId);
      
      if (!user || user.role !== 'superadmin') {
        return res.status(403).json({ message: "Insufficient permissions" });
      }

      const status = req.query.status as string;
      const requests = await storage.getMediaOutletRequests(status);
      res.json(requests);
    } catch (error) {
      console.error("Error fetching requests:", error);
      res.status(500).json({ message: "Failed to fetch requests" });
    }
  });

  app.post('/api/media-outlet-requests', isAuthenticated, async (req: any, res) => {
    try {
      const userId = req.user.claims?.sub || req.user.id;
      const requestData = insertMediaOutletRequestSchema.parse({
        ...req.body,
        requesterId: userId
      });
      
      const request = await storage.createMediaOutletRequest(requestData);
      res.status(201).json(request);
    } catch (error) {
      console.error("Error creating request:", error);
      res.status(500).json({ message: "Failed to create request" });
    }
  });

  app.patch('/api/media-outlet-requests/:id', isAuthenticated, async (req: any, res) => {
    try {
      const userId = req.user.claims?.sub || req.user.id;
      const user = await storage.getUser(userId);
      
      if (!user || user.role !== 'superadmin') {
        return res.status(403).json({ message: "Insufficient permissions" });
      }

      const { status } = req.body;
      const request = await storage.updateMediaOutletRequestStatus(req.params.id, status, userId);
      res.json(request);
    } catch (error) {
      console.error("Error updating request:", error);
      res.status(500).json({ message: "Failed to update request" });
    }
  });

  // Comment routes
  app.get('/api/articles/:articleId/comments', async (req, res) => {
    try {
      const comments = await storage.getCommentsByArticle(req.params.articleId);
      res.json(comments);
    } catch (error) {
      console.error("Error fetching comments:", error);
      res.status(500).json({ message: "Failed to fetch comments" });
    }
  });

  app.post('/api/articles/:articleId/comments', isAuthenticated, async (req: any, res) => {
    try {
      const userId = req.user.claims?.sub || req.user.id;
      const commentData = insertCommentSchema.parse({
        ...req.body,
        articleId: req.params.articleId,
        authorId: userId
      });
      
      const comment = await storage.createComment(commentData);
      res.status(201).json(comment);
    } catch (error) {
      console.error("Error creating comment:", error);
      res.status(500).json({ message: "Failed to create comment" });
    }
  });

  // Analytics routes
  app.get('/api/analytics', isAuthenticated, async (req: any, res) => {
    try {
      const userId = req.user.claims?.sub || req.user.id;
      const user = await storage.getUser(userId);
      
      if (!user || (user.role !== 'admin' && user.role !== 'superadmin')) {
        return res.status(403).json({ message: "Insufficient permissions" });
      }

      const analytics = await storage.getAnalytics();
      res.json(analytics);
    } catch (error) {
      console.error("Error fetching analytics:", error);
      res.status(500).json({ message: "Failed to fetch analytics" });
    }
  });

  // Search routes
  app.get('/api/search', async (req, res) => {
    try {
      const { q } = req.query;
      
      if (!q || typeof q !== 'string' || q.trim().length === 0) {
        return res.json({ outlets: [], articles: [] });
      }

      const results = await storage.search(q.trim());
      res.json(results);
    } catch (error) {
      console.error("Error performing search:", error);
      res.status(500).json({ message: "Failed to perform search" });
    }
  });

  const httpServer = createServer(app);
  return httpServer;
}
