import type { Express, RequestHandler } from "express";
import type { Server } from "http";
import { storage } from "./storage";
import { 
  insertCountrySchema, insertCitySchema, insertOperatorSchema, insertLineSchema 
} from "@shared/schema";
import { ZodError } from "zod";
import { 
  getPortableSession, 
  getPortableAuthRoutes, 
  isPortableAuthenticated 
} from "./portable-auth";

export async function registerRoutes(
  httpServer: Server,
  app: Express
): Promise<Server> {
  
  // Use portable auth (username/password)
  app.set("trust proxy", 1);
  app.use(getPortableSession());
  app.use(getPortableAuthRoutes());
  const authMiddleware: RequestHandler = isPortableAuthenticated;
  console.log("Using Username/Password Authentication");

  // Error handler for Zod validation
  const handleZodError = (error: unknown) => {
    if (error instanceof ZodError) {
      return { message: "Validation error", errors: error.errors };
    }
    throw error;
  };

  // --- Public Routes (Read-only) ---
  
  // Get all countries with nested data
  app.get("/api/countries", async (_req, res) => {
    try {
      const allCountries = await storage.getAllCountries();
      
      const result = await Promise.all(
        allCountries.map(async (country) => {
          const citiesData = await storage.getCitiesByCountry(country.id);
          
          const cities = await Promise.all(
            citiesData.map(async (city) => {
              const operatorsData = await storage.getOperatorsByCity(city.id);
              
              const operators = await Promise.all(
                operatorsData.map(async (operator) => {
                  const lines = await storage.getLinesByOperator(operator.id);
                  return { ...operator, lines };
                })
              );
              
              return { ...city, operators };
            })
          );
          
          return { ...country, cities };
        })
      );
      
      res.json(result);
    } catch (error) {
      console.error("Error fetching countries:", error);
      res.status(500).json({ message: "Failed to fetch countries" });
    }
  });

  // --- Protected Admin Routes ---
  
  // Countries
  app.post("/api/countries", authMiddleware, async (req, res) => {
    try {
      const data = insertCountrySchema.parse(req.body);
      const country = await storage.createCountry(data);
      res.json(country);
    } catch (error) {
      res.status(400).json(handleZodError(error));
    }
  });
  
  app.delete("/api/countries/:id", authMiddleware, async (req, res) => {
    try {
      await storage.deleteCountry(req.params.id);
      res.json({ success: true });
    } catch (error) {
      res.status(500).json({ message: "Failed to delete country" });
    }
  });
  
  // Cities
  app.post("/api/cities", authMiddleware, async (req, res) => {
    try {
      const data = insertCitySchema.parse(req.body);
      const city = await storage.createCity(data);
      res.json(city);
    } catch (error) {
      res.status(400).json(handleZodError(error));
    }
  });
  
  app.delete("/api/cities/:id", authMiddleware, async (req, res) => {
    try {
      await storage.deleteCity(req.params.id);
      res.json({ success: true });
    } catch (error) {
      res.status(500).json({ message: "Failed to delete city" });
    }
  });
  
  // Operators
  app.post("/api/operators", authMiddleware, async (req, res) => {
    try {
      const data = insertOperatorSchema.parse(req.body);
      const operator = await storage.createOperator(data);
      res.json(operator);
    } catch (error) {
      res.status(400).json(handleZodError(error));
    }
  });
  
  app.delete("/api/operators/:id", authMiddleware, async (req, res) => {
    try {
      await storage.deleteOperator(req.params.id);
      res.json({ success: true });
    } catch (error) {
      res.status(500).json({ message: "Failed to delete operator" });
    }
  });
  
  // Lines
  app.post("/api/lines", authMiddleware, async (req, res) => {
    try {
      const data = insertLineSchema.parse(req.body);
      const line = await storage.createLine(data);
      res.json(line);
    } catch (error) {
      res.status(400).json(handleZodError(error));
    }
  });
  
  app.patch("/api/lines/:id", authMiddleware, async (req, res) => {
    try {
      const data = insertLineSchema.partial().parse(req.body);
      const line = await storage.updateLine(req.params.id, data);
      if (!line) {
        return res.status(404).json({ message: "Line not found" });
      }
      res.json(line);
    } catch (error) {
      res.status(400).json(handleZodError(error));
    }
  });
  
  app.delete("/api/lines/:id", authMiddleware, async (req, res) => {
    try {
      await storage.deleteLine(req.params.id);
      res.json({ success: true });
    } catch (error) {
      res.status(500).json({ message: "Failed to delete line" });
    }
  });

  return httpServer;
}
