import { createError } from 'h3';
import type { AuthInfoResponse } from '~/types/auth';
import {
  createUserSession,
  deleteUserSession,
  getUserSession,
} from '~/server/utils/sessionStore';

type SessionStoreRequest = {
  accessToken?: string;
  refreshToken?: string;
};

const DEFAULT_SESSION_SECONDS = 60 * 60; // 1 hour


const parseJwtPayload = (token: string): { exp?: number } | null => {
  try {
    const payload = token.split('.')[1];
    if (!payload) return null;

    const normalized = payload.replace(/-/g, '+').replace(/_/g, '/');
    const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, '=');
    const decoded = Buffer.from(padded, 'base64').toString();

    return JSON.parse(decoded) as { exp?: number };
  } catch {
    return null;
  }
};

export default defineEventHandler(async (event) => {
  const body = await readBody<SessionStoreRequest>(event);

  const accessToken = body?.accessToken;
  const refreshToken = body?.refreshToken;

  if (!accessToken || !refreshToken) {
    throw createError({
      statusCode: 400,
      statusMessage: 'accessToken and refreshToken are required',
    });
  }

  const config = useRuntimeConfig();
  const baseUrl = config.public.baseUrl;
  const authInfoUrl = `${baseUrl}/api/v1/auth/info`;

  let authInfoResponse: AuthInfoResponse;
  try {
    authInfoResponse = await $fetch<AuthInfoResponse>(authInfoUrl, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${accessToken}`,
      },
    });
  } catch (error: any) {
    throw createError({
      statusCode: 401,
      statusMessage:
        error?.data?.message || error?.message || 'Failed to fetch auth info',
    });
  }

  if (!authInfoResponse?.data) {
    throw createError({
      statusCode: 502,
      statusMessage: 'Invalid auth info response',
    });
  }

  const now = Date.now();
  const refreshPayload = parseJwtPayload(refreshToken);
  const refreshExpSeconds = refreshPayload?.exp;

  const expiresAt =
    typeof refreshExpSeconds === 'number' && refreshExpSeconds > 0
      ? refreshExpSeconds * 1000
      : now + DEFAULT_SESSION_SECONDS * 1000;

  const maxAge = Math.max(Math.floor((expiresAt - now) / 1000), 60);

  const previousSessionId = getCookie(event, 'user_session');
  if (previousSessionId && getUserSession(previousSessionId)) {
    deleteUserSession(previousSessionId);
  }

  const sessionId = createUserSession({
    user: {
      auth_provider: authInfoResponse.data.auth_provider || 'jwt',
      email: authInfoResponse.data.email,
      name: authInfoResponse.data.name,
      role: authInfoResponse.data.role,
      user_id: authInfoResponse.data.user_id,
      username: authInfoResponse.data.username,
    },
    accessToken,
    refreshToken,
    expiresAt,
  });

  const isSecure =
    process.env.NODE_ENV === 'production' && event.node.req.headers['x-forwarded-proto'] === 'https';

  setCookie(event, 'user_session', sessionId, {
    httpOnly: true,
    secure: isSecure,
    sameSite: 'lax',
    maxAge,
    path: '/',
  });

  return {
    success: true,
    message: 'Session stored successfully',
    expiresAt,
  };
});
