import { getStatus as getYtdlpStatus } from "../ytdlp";
import { config } from "../config";
import { state } from "../state";
import { getOrCreateUser } from "./helpers";

// Auth routes
import {
  handleSignup,
  handleLogin,
  handleLogout,
  handleGetMe,
  handleKickOthers,
  handleListUsers,
  handleGrantPermission,
  handleRevokePermission,
} from "./auth";

// Channel routes
import {
  handleListChannels,
  handleCreateChannel,
  handleDeleteChannel,
  handleGetChannel,
  handleJump,
  handleSeek,
  handleModifyQueue,
  handleSetMode,
  handleRenameChannel,
} from "./channels";

// Track routes
import {
  handleGetLibrary,
  handleUpload,
  handleGetTrack,
} from "./tracks";

// Fetch routes (yt-dlp)
import {
  handleFetch,
  handleFetchConfirm,
  handleGetFetchQueue,
  handleCancelFetchItem,
  handleCancelAllFetchItems,
} from "./fetch";

// Playlist routes
import {
  handleListPlaylists,
  handleCreatePlaylist,
  handleGetPlaylist,
  handleUpdatePlaylist,
  handleDeletePlaylist,
  handleModifyPlaylistTracks,
  handleSharePlaylist,
  handleUnsharePlaylist,
  handleGetSharedPlaylist,
  handleCopySharedPlaylist,
} from "./playlists";

// Static file serving
import { handleStatic } from "./static";

export function createRouter() {
  return async function fetch(req: Request, server: any): Promise<Response | undefined> {
    const url = new URL(req.url);
    const path = url.pathname;

    // WebSocket upgrade for channels
    if (path.match(/^\/api\/channels\/([^/]+)\/ws$/)) {
      const id = path.split("/")[3];
      if (!state.channels.has(id)) return new Response("Channel not found", { status: 404 });
      const { user } = getOrCreateUser(req, server);
      const ok = server.upgrade(req, { data: { channelId: id, userId: user?.id ?? null, username: user?.username ?? 'Guest' } });
      if (ok) return undefined;
      return new Response("WebSocket upgrade failed", { status: 500 });
    }

    // API: server status (public)
    if (path === "/api/status") {
      return Response.json({
        name: "MusicRoom",
        version: "1.0.0",
        allowGuests: config.allowGuests,
        allowSignups: true,
        channelCount: state.channels.size,
        defaultPermissions: config.defaultPermissions,
        ytdlp: getYtdlpStatus()
      });
    }

    // Channel routes
    if (path === "/api/channels" && req.method === "GET") {
      return handleListChannels(req, server);
    }
    if (path === "/api/channels" && req.method === "POST") {
      return handleCreateChannel(req, server);
    }

    const channelDeleteMatch = path.match(/^\/api\/channels\/([^/]+)$/);
    if (channelDeleteMatch && req.method === "DELETE") {
      return handleDeleteChannel(req, server, channelDeleteMatch[1]);
    }

    const channelPatchMatch = path.match(/^\/api\/channels\/([^/]+)$/);
    if (channelPatchMatch && req.method === "PATCH") {
      return handleRenameChannel(req, server, channelPatchMatch[1]);
    }

    const channelGetMatch = path.match(/^\/api\/channels\/([^/]+)$/);
    if (channelGetMatch && req.method === "GET") {
      return handleGetChannel(channelGetMatch[1]);
    }

    const jumpMatch = path.match(/^\/api\/channels\/([^/]+)\/jump$/);
    if (jumpMatch && req.method === "POST") {
      return handleJump(req, server, jumpMatch[1]);
    }

    const seekMatch = path.match(/^\/api\/channels\/([^/]+)\/seek$/);
    if (seekMatch && req.method === "POST") {
      return handleSeek(req, server, seekMatch[1]);
    }

    const queueMatch = path.match(/^\/api\/channels\/([^/]+)\/queue$/);
    if (queueMatch && req.method === "PATCH") {
      return handleModifyQueue(req, server, queueMatch[1]);
    }

    const modeMatch = path.match(/^\/api\/channels\/([^/]+)\/mode$/);
    if (modeMatch && req.method === "POST") {
      return handleSetMode(req, server, modeMatch[1]);
    }

    // Library routes
    if (path === "/api/library") {
      return handleGetLibrary(req, server);
    }

    if (path === "/api/upload" && req.method === "POST") {
      return handleUpload(req, server);
    }

    // Fetch routes (yt-dlp)
    if (path === "/api/fetch" && req.method === "POST") {
      return handleFetch(req, server);
    }
    if (path === "/api/fetch/confirm" && req.method === "POST") {
      return handleFetchConfirm(req, server);
    }
    if (path === "/api/fetch" && req.method === "GET") {
      return handleGetFetchQueue(req, server);
    }
    if (path === "/api/fetch" && req.method === "DELETE") {
      return handleCancelAllFetchItems(req, server);
    }
    const fetchCancelMatch = path.match(/^\/api\/fetch\/([^/]+)$/);
    if (fetchCancelMatch && req.method === "DELETE") {
      return handleCancelFetchItem(req, server, fetchCancelMatch[1]);
    }

    // Playlist routes
    if (path === "/api/playlists" && req.method === "GET") {
      return handleListPlaylists(req, server);
    }
    if (path === "/api/playlists" && req.method === "POST") {
      return handleCreatePlaylist(req, server);
    }

    const sharedPlaylistMatch = path.match(/^\/api\/playlists\/shared\/([^/]+)$/);
    if (sharedPlaylistMatch && req.method === "GET") {
      return handleGetSharedPlaylist(req, server, sharedPlaylistMatch[1]);
    }
    if (sharedPlaylistMatch && req.method === "POST") {
      return handleCopySharedPlaylist(req, server, sharedPlaylistMatch[1]);
    }

    const playlistMatch = path.match(/^\/api\/playlists\/([^/]+)$/);
    if (playlistMatch && req.method === "GET") {
      return handleGetPlaylist(req, server, playlistMatch[1]);
    }
    if (playlistMatch && req.method === "PATCH") {
      return handleUpdatePlaylist(req, server, playlistMatch[1]);
    }
    if (playlistMatch && req.method === "DELETE") {
      return handleDeletePlaylist(req, server, playlistMatch[1]);
    }

    const playlistTracksMatch = path.match(/^\/api\/playlists\/([^/]+)\/tracks$/);
    if (playlistTracksMatch && req.method === "PATCH") {
      return handleModifyPlaylistTracks(req, server, playlistTracksMatch[1]);
    }

    const playlistShareMatch = path.match(/^\/api\/playlists\/([^/]+)\/share$/);
    if (playlistShareMatch && req.method === "POST") {
      return handleSharePlaylist(req, server, playlistShareMatch[1]);
    }
    if (playlistShareMatch && req.method === "DELETE") {
      return handleUnsharePlaylist(req, server, playlistShareMatch[1]);
    }

    // Auth routes
    if (path === "/api/auth/signup" && req.method === "POST") {
      return handleSignup(req, server);
    }
    if (path === "/api/auth/login" && req.method === "POST") {
      return handleLogin(req, server);
    }
    if (path === "/api/auth/logout" && req.method === "POST") {
      return handleLogout(req);
    }
    if (path === "/api/auth/me") {
      return handleGetMe(req, server);
    }
    if (path === "/api/auth/kick-others" && req.method === "POST") {
      return handleKickOthers(req, server);
    }

    // Admin routes
    if (path === "/api/admin/users" && req.method === "GET") {
      return handleListUsers(req, server);
    }

    const permissionsMatch = path.match(/^\/api\/admin\/users\/(\d+)\/permissions$/);
    if (permissionsMatch && req.method === "POST") {
      return handleGrantPermission(req, server, parseInt(permissionsMatch[1]));
    }
    if (permissionsMatch && req.method === "DELETE") {
      return handleRevokePermission(req, server, parseInt(permissionsMatch[1]));
    }

    // Track serving (must be after other /api/tracks routes)
    const trackMatch = path.match(/^\/api\/tracks\/(.+)$/);
    if (trackMatch) {
      return handleGetTrack(req, server, decodeURIComponent(trackMatch[1]));
    }

    // Static files
    const staticResponse = await handleStatic(path);
    if (staticResponse) return staticResponse;

    return new Response("Not found", { status: 404 });
  };
}
