/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   exit.c                                             :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: sede-san <sede-san@student.42madrid.com    +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2025/10/30 01:20:48 by sede-san          #+#    #+#             */
/*   Updated: 2026/02/08 21:16:18 by sede-san         ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

#include "builtins.h"
#include <limits.h>

static uint8_t	get_uint8_from_num(const char *arg, uint8_t *status);
static uint8_t	has_overflow(
					uint64_t n,
					char digit,
					uint64_t limit
					);
static uint8_t	resolve_exit_status(
					t_command cmd,
					t_minishell *msh,
					uint8_t *exit_status
					);

uint8_t	builtin_exit(
	t_command cmd,
	t_minishell *msh
)
{
	uint8_t	exit_status;

	if (isatty(STDIN_FILENO))
		ft_eputendl("exit");
	if (!resolve_exit_status(cmd, msh, &exit_status))
		return (msh->exit_status);
	msh->exit = true;
	msh->exit_status = exit_status;
	return (exit_status);
}

static uint8_t	resolve_exit_status(
	t_command cmd,
	t_minishell *msh,
	uint8_t *exit_status
){
	if (cmd.argc == 1)
		*exit_status = msh->exit_status;
	else if (!get_uint8_from_num(cmd.argv[1], exit_status))
	{
		ft_eprintf("minishell: exit: %s: numeric argument required\n",
			cmd.argv[1]);
		msh->exit = true;
		msh->exit_status = 2;
		return (0);
	}
	else if (cmd.argc > 2)
	{
		ft_eputendl("minishell: exit: too many arguments");
		msh->exit_status = EXIT_FAILURE;
		return (0);
	}
	return (1);
}

static uint8_t	get_uint8_from_num(
	const char *arg,
	uint8_t *status
){
	uint64_t	n;
	uint64_t	limit;
	int			sign;

	if (arg == NULL || *arg == '\0')
		return (0);
	n = 0;
	sign = 1;
	if (*arg == '+' || *arg == '-')
		if (*arg++ == '-')
			sign = -1;
	if (*arg == '\0')
		return (0);
	limit = LONG_MAX;
	if (sign == -1)
		limit = (uint64_t)LONG_MAX + 1;
	while (*arg != '\0')
	{
		if (!ft_isdigit(*arg) || has_overflow(n, *arg, limit))
			return (0);
		n = (n * 10) + (*arg++ - '0');
	}
	*status = (uint8_t)(n * sign);
	return (1);
}

static uint8_t	has_overflow(
	uint64_t n,
	char digit,
	uint64_t limit
){
	if (n > (limit / 10))
		return (1);
	if (n == (limit / 10) && (uint64_t)(digit - '0') > (limit % 10))
		return (1);
	return (0);
}
