#include "core/system/shutdown.hpp"

#include <sys/types.h>  // Para pid_t

#include <cstdlib>   // Para WEXITSTATUS
#include <iostream>  // Para char_traits, basic_ostream, operator<<, cerr
#include <vector>    // Para vector

#ifdef _WIN32
#include <windows.h>
#else
#include <sys/wait.h>  // Para waitpid
#include <unistd.h>    // Para _exit, execvp, fork
#endif

namespace SystemShutdown {

#ifndef _WIN32
    // Función auxiliar para sistemas Unix-like
    auto executeUnixShutdown(const char* command, const std::vector<char*>& args) -> ShutdownResult {
        pid_t pid = fork();

        if (pid == 0) {
            // Proceso hijo
            execvp(command, args.data());
            // Si llegamos aquí, execvp falló
            std::cerr << "Error: No se pudo ejecutar " << command << '\n';
            _exit(1);
        } else if (pid > 0) {
            // Proceso padre
            int status;
            waitpid(pid, &status, 0);
            return (WEXITSTATUS(status) == 0) ? ShutdownResult::SUCCESS : ShutdownResult::ERROR_SYSTEM_CALL;
        } else {
            return ShutdownResult::ERROR_FORK_FAILED;
        }
    }
#endif

    // Implementación de las funciones públicas
    auto shutdownSystem() -> ShutdownResult {
        ShutdownConfig config;
        return shutdownSystem(config);
    }

    auto shutdownSystem(int delay_seconds, bool force_apps) -> ShutdownResult {
        ShutdownConfig config;
        config.delay_seconds = delay_seconds;
        config.force_close_apps = force_apps;
        return shutdownSystem(config);
    }

    auto shutdownSystem(const ShutdownConfig& config) -> ShutdownResult {
#ifdef _WIN32
        // Windows: Usar CreateProcess
        STARTUPINFOA si = {0};
        PROCESS_INFORMATION pi = {0};
        si.cb = sizeof(si);

        // Crear comando con el delay especificado
        std::string command = "shutdown.exe /s /t " + std::to_string(config.delay_seconds);
        if (config.force_close_apps) {
            command += " /f";
        }

        // CreateProcess necesita un array de char modificable
        char* cmd_buffer = new char[command.length() + 1];
        strcpy(cmd_buffer, command.c_str());

        bool success = CreateProcessA(
            NULL,        // lpApplicationName
            cmd_buffer,  // lpCommandLine
            NULL,        // lpProcessAttributes
            NULL,        // lpThreadAttributes
            FALSE,       // bInheritHandles
            0,           // dwCreationFlags
            NULL,        // lpEnvironment
            NULL,        // lpCurrentDirectory
            &si,         // lpStartupInfo
            &pi          // lpProcessInformation
        );

        delete[] cmd_buffer;

        if (success) {
            CloseHandle(pi.hProcess);
            CloseHandle(pi.hThread);
            return ShutdownResult::SUCCESS;
        } else {
            DWORD error = GetLastError();
            if (error == ERROR_ACCESS_DENIED) {
                return ShutdownResult::ERROR_PERMISSION;
            }
            return ShutdownResult::ERROR_SYSTEM_CALL;
        }

#elif __APPLE__
        // macOS - apagado inmediato
        std::vector<char*> args = {
            const_cast<char*>("shutdown"),
            const_cast<char*>("-h"),
            const_cast<char*>("now"),
            nullptr};

        return executeUnixShutdown("shutdown", args);

#elif __linux__
        // Linux - apagado inmediato
        std::vector<char*> args = {
            const_cast<char*>("shutdown"),
            const_cast<char*>("-h"),
            const_cast<char*>("now"),
            nullptr};

        return executeUnixShutdown("shutdown", args);

#else
        return ShutdownResult::ERROR_UNSUPPORTED;
#endif
    }

    auto resultToString(ShutdownResult result) -> const char* {
        switch (result) {
            case ShutdownResult::SUCCESS:
                return "Apagado iniciado exitosamente";
            case ShutdownResult::ERROR_PERMISSION:
                return "Error: Permisos insuficientes";
            case ShutdownResult::ERROR_SYSTEM_CALL:
                return "Error: Fallo en la llamada al sistema";
            case ShutdownResult::ERROR_FORK_FAILED:
                return "Error: No se pudo crear proceso hijo";
            case ShutdownResult::ERROR_UNSUPPORTED:
                return "Error: Sistema operativo no soportado";
            default:
                return "Error desconocido";
        }
    }

    auto isShutdownSupported() -> bool {
#if defined(_WIN32) || defined(__APPLE__) || defined(__linux__)
        return true;
#else
        return false;
#endif
    }

    auto getRequiredPermissions() -> const char* {
#ifdef _WIN32
        return "Requiere permisos de Administrador en Windows";
#elif defined(__APPLE__) || defined(__linux__)
        return "Requiere permisos de root/sudo en Unix";
#else
        return "Sistema no soportado";
#endif
    }

}  // namespace SystemShutdown