import {
  createUser,
  findUserByUsername,
  validatePassword,
  createSession,
  createGuestSession,
  deleteSession,
  getUserPermissions,
  getAllUsers,
  grantPermission,
  revokePermission,
} from "../db";
import {
  getUser,
  requirePermission,
  setSessionCookie,
  clearSessionCookie,
  getClientInfo,
} from "../auth";
import { config } from "../config";
import { state } from "../state";
import { getOrCreateUser, userHasPermission } from "./helpers";

// Auth: signup
export async function handleSignup(req: Request, server: any): Promise<Response> {
  try {
    const { username, password } = await req.json();
    if (!username || !password) {
      return Response.json({ error: "Username and password required" }, { status: 400 });
    }
    if (username.length < 3 || password.length < 6) {
      return Response.json({ error: "Username min 3 chars, password min 6 chars" }, { status: 400 });
    }
    const existing = findUserByUsername(username);
    if (existing) {
      return Response.json({ error: "Username already taken" }, { status: 400 });
    }
    const user = await createUser(username, password);
    const userAgent = req.headers.get("user-agent") ?? undefined;
    const ipAddress = req.headers.get("x-forwarded-for")?.split(",")[0]?.trim()
      ?? req.headers.get("x-real-ip")
      ?? server.requestIP(req)?.address
      ?? undefined;
    const token = createSession(user.id, userAgent, ipAddress);
    console.log(`[AUTH] Signup: user="${username}" id=${user.id} admin=${user.is_admin} session=${token} ip=${ipAddress} ua="${userAgent?.slice(0, 50)}..."`);
    state.library.logActivity("account_created", { title: user.is_admin ? "admin" : "user" }, { id: user.id, username: user.username });
    return Response.json(
      { user: { id: user.id, username: user.username, isAdmin: user.is_admin } },
      { headers: { "Set-Cookie": setSessionCookie(token) } }
    );
  } catch (e) {
    return Response.json({ error: "Signup failed" }, { status: 500 });
  }
}

// Auth: login
export async function handleLogin(req: Request, server: any): Promise<Response> {
  try {
    const { username, password } = await req.json();
    const user = findUserByUsername(username);
    if (!user || !(await validatePassword(user, password))) {
      console.log(`[AUTH] Login failed: user="${username}"`);
      return Response.json({ error: "Invalid username or password" }, { status: 401 });
    }
    const userAgent = req.headers.get("user-agent") ?? undefined;
    const ipAddress = req.headers.get("x-forwarded-for")?.split(",")[0]?.trim()
      ?? req.headers.get("x-real-ip")
      ?? server.requestIP(req)?.address
      ?? undefined;
    const token = createSession(user.id, userAgent, ipAddress);
    console.log(`[AUTH] Login: user="${username}" id=${user.id} session=${token} ip=${ipAddress} ua="${userAgent?.slice(0, 50)}..."`);
    return Response.json(
      { user: { id: user.id, username: user.username, isAdmin: user.is_admin } },
      { headers: { "Set-Cookie": setSessionCookie(token) } }
    );
  } catch (e) {
    return Response.json({ error: "Login failed" }, { status: 500 });
  }
}

// Auth: logout
export function handleLogout(req: Request): Response {
  const token = req.headers.get("cookie")?.match(/blastoise_session=([^;]+)/)?.[1];
  if (token) {
    const { validateSession } = require("../db");
    const user = validateSession(token);
    console.log(`[AUTH] Logout: user="${user?.username ?? "unknown"}" session=${token}`);
    deleteSession(token);
  }
  return Response.json(
    { success: true },
    { headers: { "Set-Cookie": clearSessionCookie() } }
  );
}

// Auth: get current user
export function handleGetMe(req: Request, server: any): Response {
  const { user, headers } = getOrCreateUser(req, server);
  if (!user) {
    return Response.json({ user: null });
  }
  const permissions = getUserPermissions(user.id);
  const effectivePermissions = [...permissions];
  if (config.defaultPermissions) {
    for (const perm of config.defaultPermissions) {
      if (user.is_guest && perm === "control") continue;
      effectivePermissions.push({
        id: 0,
        user_id: user.id,
        resource_type: "channel",
        resource_id: null,
        permission: perm,
      });
    }
  }
  return Response.json({
    user: { id: user.id, username: user.username, isAdmin: user.is_admin, isGuest: user.is_guest },
    permissions: effectivePermissions,
  }, { headers });
}

// Kick all other clients for current user
export function handleKickOthers(req: Request, server: any): Response {
  const { user } = getOrCreateUser(req, server);
  if (!user) {
    return Response.json({ error: "Not authenticated" }, { status: 401 });
  }

  const connections = state.userConnections.get(user.id);
  if (!connections || connections.size === 0) {
    return Response.json({ kicked: 0 });
  }

  let kickedCount = 0;
  for (const ws of connections) {
    ws.send(JSON.stringify({ type: "kick", reason: "Kicked by another session" }));
    kickedCount++;
  }

  console.log(`[Kick] User ${user.username} kicked ${kickedCount} other clients`);
  return Response.json({ kicked: kickedCount });
}

// Admin: list users
export function handleListUsers(req: Request, server: any): Response {
  try {
    requirePermission(req, "global", null, "admin", server);
    return Response.json(getAllUsers());
  } catch (e) {
    if (e instanceof Response) return e;
    return Response.json({ error: "Failed" }, { status: 500 });
  }
}

// Admin: grant permission
export async function handleGrantPermission(req: Request, server: any, userId: number): Promise<Response> {
  try {
    requirePermission(req, "global", null, "admin", server);
    const { resourceType, resourceId, permission } = await req.json();
    grantPermission(userId, resourceType, resourceId, permission);
    return Response.json({ success: true });
  } catch (e) {
    if (e instanceof Response) return e;
    return Response.json({ error: "Failed" }, { status: 500 });
  }
}

// Admin: revoke permission
export async function handleRevokePermission(req: Request, server: any, userId: number): Promise<Response> {
  try {
    requirePermission(req, "global", null, "admin", server);
    const { resourceType, resourceId, permission } = await req.json();
    revokePermission(userId, resourceType, resourceId, permission);
    return Response.json({ success: true });
  } catch (e) {
    if (e instanceof Response) return e;
    return Response.json({ error: "Failed" }, { status: 500 });
  }
}
