import { FastifyInstance } from "fastify";
import prisma from "../../config/database";
import { requireAuth } from "../../middleware/auth";
import { success, error, parseId } from "../../utils/response";
import { hashToken } from "../../services/auth";
import { logAudit } from "../../services/audit";

/** Parse user-agent string into browser, OS, and device icon */
function parseUserAgent(ua: string | null): {
  browser: string;
  os: string;
  icon: string;
} {
  if (!ua)
    return {
      browser: "Neznámý prohlížeč",
      os: "Neznámý systém",
      icon: "monitor",
    };

  let browser = "Neznámý prohlížeč";
  if (ua.includes("Edg/")) browser = "Edge";
  else if (ua.includes("OPR/") || ua.includes("Opera")) browser = "Opera";
  else if (ua.includes("Chrome/")) browser = "Chrome";
  else if (ua.includes("Safari/") && !ua.includes("Chrome")) browser = "Safari";
  else if (ua.includes("Firefox/")) browser = "Firefox";

  let os = "Neznámý systém";
  if (ua.includes("Windows")) os = "Windows";
  else if (ua.includes("Mac OS X") || ua.includes("Macintosh")) os = "macOS";
  else if (ua.includes("Linux") && !ua.includes("Android")) os = "Linux";
  else if (ua.includes("Android")) os = "Android";
  else if (ua.includes("iPhone") || ua.includes("iPad")) os = "iOS";

  let icon = "monitor";
  if (
    ua.includes("Mobile") ||
    ua.includes("iPhone") ||
    ua.includes("Android")
  ) {
    icon =
      ua.includes("iPad") || ua.includes("Tablet") ? "tablet" : "smartphone";
  }

  return { browser, os, icon };
}

export default async function sessionsRoutes(
  fastify: FastifyInstance,
): Promise<void> {
  // GET /api/admin/sessions — list active sessions for current user
  fastify.get("/", { preHandler: requireAuth }, async (request, reply) => {
    const authData = request.authData!;
    const currentToken = request.cookies?.refresh_token;
    const currentHash = currentToken ? hashToken(currentToken) : null;

    const sessions = await prisma.refresh_tokens.findMany({
      where: {
        user_id: authData.userId,
        replaced_at: null,
        expires_at: { gt: new Date() },
      },
      orderBy: { created_at: "desc" },
    });

    const enriched = sessions.map((s) => {
      const device_info = parseUserAgent(s.user_agent);
      return {
        id: s.id,
        is_current: currentHash ? s.token_hash === currentHash : false,
        device_info,
        ip_address: s.ip_address || "",
        created_at: s.created_at ?? "",
      };
    });

    return success(reply, enriched);
  });

  // DELETE /api/admin/sessions/:id — delete specific session
  fastify.delete<{ Params: { id: string } }>(
    "/:id",
    { preHandler: requireAuth },
    async (request, reply) => {
      const id = parseId((request.params as any).id, reply);
      if (id === null) return;
      const authData = request.authData!;

      const session = await prisma.refresh_tokens.findFirst({
        where: { id, user_id: authData.userId },
      });
      if (!session) return error(reply, "Relace nenalezena", 404);

      await prisma.refresh_tokens.update({
        where: { id },
        data: { replaced_at: new Date() },
      });
      await logAudit({
        request,
        authData,
        action: "delete",
        entityType: "session",
        entityId: id,
        description: `Ukončena relace #${id} (${session.ip_address ?? "?"})`,
      });
      return success(reply, null, 200, "Relace ukončena");
    },
  );

  // DELETE /api/admin/sessions — delete all sessions except current
  fastify.delete("/", { preHandler: requireAuth }, async (request, reply) => {
    const authData = request.authData!;
    const query = request.query as Record<string, unknown>;

    if (query.action === "all") {
      // Get current token from cookie to exclude (hash it to match stored token_hash)
      const currentToken = request.cookies?.refresh_token;
      const currentHash = currentToken ? hashToken(currentToken) : null;

      if (!currentHash) {
        return error(reply, "Nelze identifikovat aktuální relaci", 400);
      }

      const terminated = await prisma.refresh_tokens.updateMany({
        where: {
          user_id: authData.userId,
          replaced_at: null,
          token_hash: { not: currentHash },
        },
        data: { replaced_at: new Date() },
      });
      await logAudit({
        request,
        authData,
        action: "delete",
        entityType: "session",
        description: `Ukončeny všechny ostatní relace (${terminated.count})`,
      });
      return success(reply, null, 200, "Všechny ostatní relace ukončeny");
    }

    return error(reply, "Neplatná akce", 400);
  });
}
