#include "application.h"

#include "camera_service.h"
#include "device_config.h"
#include "mqtt_service.h"
#include "time_sync.h"
#include "webrtc_stream.h"

#include <rtc/rtc.hpp>

#include <csignal>
#include <cstdlib>
#include <iostream>
#include <limits.h>
#include <string>
#include <unistd.h>

namespace app {
namespace {

volatile std::sig_atomic_t running = 1;

void on_signal(int){
    running = 0;
}

std::string executable_dir(){
    char path[PATH_MAX];
    const ssize_t len = readlink("/proc/self/exe", path, sizeof(path) - 1);
    if(len <= 0) return ".";
    path[len] = '\0';
    std::string full(path);
    const size_t slash = full.rfind('/');
    return slash == std::string::npos ? "." : full.substr(0, slash);
}

void configure_ca_certificate(const std::string &app_dir){
    const char *configured = std::getenv("WEBRTCPUSH_CA_CERT");
    if(configured && *configured) return;

    const std::string ca_path = app_dir + "/lib/ca-certificates.crt";
    if(access(ca_path.c_str(), R_OK) != 0){
        std::cerr << "[app] CA certificate not found: " << ca_path << "\n";
        return;
    }
    setenv("WEBRTCPUSH_CA_CERT", ca_path.c_str(), 0);
    setenv("SSL_CERT_FILE", ca_path.c_str(), 0);
    std::cerr << "[app] CA certificate: " << ca_path << "\n";
}

} // namespace

int run_application(int argc, char **argv){
    if(std::getenv("WEBRTCPUSH_RTC_DEBUG"))
        rtc::InitLogger(rtc::LogLevel::Debug);

    running = 1;
    signal(SIGINT, on_signal);
    signal(SIGTERM, on_signal);

    const std::string app_dir = executable_dir();
    webrtcpush::StreamConfig config;
    load_device_config(app_dir + "/device.config", config);

    const ParseResult parse_result = apply_command_line(argc, argv, config);
    if(parse_result == ParseResult::Help) return 0;
    if(parse_result == ParseResult::Error || !validate_config(config)) return 1;

    configure_ca_certificate(app_dir);
    if(config.source == "camera" && !driver::camera::stop_firmware_service())
        return 7;

    std::cerr << "[app] deviceid=" << config.room
              << " output=" << config.width << "x" << config.height
              << " fps=" << config.fps << " bitrate=" << config.bitrate
              << " gop=" << config.gop << "\n";

    if(!time_sync_ensure()){
        std::cerr << "[app] SNTP sync failed; TLS may fail until system time is corrected\n";
    }

    mqtt::Service mqtt_service(config.room);
    if(!mqtt_service.start())
        std::cerr << "[app] MQTT startup failed; WebRTC will continue\n";

    const int stream_result = webrtcpush::run_stream(config, running);
    mqtt_service.stop();
    return stream_result;
}

} // namespace app
