import type { Express, Request, Response } from "express";
import { getDb, getUserByOpenId } from "../db.ts";
import { users, wallets } from "../../drizzle/schema.ts";
import { eq } from "drizzle-orm";
import { getSessionCookieOptions } from "./cookies.ts";
import { sdk } from "./sdk.ts";
import { COOKIE_NAME } from "../../shared/const.ts";
import bcrypt from "bcrypt";

const ONE_YEAR_MS = 365 * 24 * 60 * 60 * 1000;

export async function registerEmailAuthRoutes(app: Express) {
  // Signup endpoint
  app.post("/api/auth/signup", async (req: Request, res: Response) => {
    try {
      const { username, password, email } = req.body;

      if (!username || !password) {
        res.status(400).json({ error: "Username and password are required" });
        return;
      }

      if (password.length < 8) {
        res.status(400).json({ error: "Password must be at least 8 characters" });
        return;
      }

      const db = await getDb();
      if (!db) {
        res.status(500).json({ error: "Database connection failed" });
        return;
      }

      // Check if username already exists
      const existing = await db
        .select()
        .from(users)
        .where(eq(users.username, username))
        .limit(1);

      if (existing.length > 0) {
        res.status(409).json({ error: "Username already taken" });
        return;
      }

      // Hash password
      const passwordHash = await bcrypt.hash(password, 10);

      // Create unique openId
      const openId = `user_${username}_${Date.now()}`;

      // Insert user
      const database = await getDb();
      if (!database) {
        res.status(500).json({ error: "Database connection failed" });
        return;
      }

      await database.insert(users).values({
        openId,
        username,
        email: email || null,
        passwordHash,
        loginMethod: "username",
        lastSignedIn: new Date(),
      });

      // Get the newly created user to get their ID
      const newUser = await getUserByOpenId(openId);
      if (newUser) {
        // Initialize wallet with starting balances: 5000 GC + 10 SC
        try {
          await database.insert(wallets).values({
            userId: newUser.id,
            gcBalance: "5000.00",
            scBalance: "10.00",
          });
          console.log(`[Auth] Wallet initialized for user ${newUser.id}`);
        } catch (walletError) {
          console.warn(`[Auth] Failed to initialize wallet for user ${newUser.id}:`, walletError);
        }
      }

      // Create session token
      const sessionToken = await sdk.createSessionToken(openId, {
        name: username,
        expiresInMs: ONE_YEAR_MS,
      });

      // Set cookie
      const cookieOptions = getSessionCookieOptions(req);
      res.cookie(COOKIE_NAME, sessionToken, {
        ...cookieOptions,
        maxAge: ONE_YEAR_MS,
      });

      res.json({
        success: true,
        user: { id: openId, username, email: email || null },
      });
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error);
      console.error("[Auth] Signup failed:", errorMessage);
      res.status(500).json({ error: "Signup failed", details: errorMessage });
    }
  });

  // Login endpoint
  app.post("/api/auth/login", async (req: Request, res: Response) => {
    try {
      const { username, password } = req.body;

      if (!username || !password) {
        res.status(400).json({ error: "Username and password are required" });
        return;
      }

      const db = await getDb();
      if (!db) {
        res.status(500).json({ error: "Database connection failed" });
        return;
      }

      // Find user
      const result = await db
        .select()
        .from(users)
        .where(eq(users.username, username))
        .limit(1);

      const user = result[0];

      if (!user || !user.passwordHash) {
        res.status(401).json({ error: "Invalid username or password" });
        return;
      }

      // Verify password
      const isValid = await bcrypt.compare(password, user.passwordHash);

      if (!isValid) {
        res.status(401).json({ error: "Invalid username or password" });
        return;
      }

      // Update last signed in
      await db
        .update(users)
        .set({ lastSignedIn: new Date() })
        .where(eq(users.id, user.id));

      // Create session token
      const sessionToken = await sdk.createSessionToken(user.openId, {
        name: user.username || "User",
        expiresInMs: ONE_YEAR_MS,
      });

      // Set cookie
      const cookieOptions = getSessionCookieOptions(req);
      res.cookie(COOKIE_NAME, sessionToken, {
        ...cookieOptions,
        maxAge: ONE_YEAR_MS,
      });

      res.json({
        success: true,
        user: { id: user.id, username: user.username, email: user.email },
      });
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error);
      console.error("[Auth] Login failed:", errorMessage);
      res.status(500).json({ error: "Login failed", details: errorMessage });
    }
  });
}
