/*
 *
 *    Copyright (c) 2025 Project CHIP Authors
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

#include "DeviceManager.h"

#include <app/data-model/Nullable.h>
#include <commands/interactive/InteractiveCommands.h>
#include <crypto/RandUtils.h>
#include <lib/support/StringBuilder.h>
#include <webrtc-manager/WebRTCManager.h>

#include <chrono>
#include <cstring>
#include <errno.h>
#include <map>
#include <signal.h>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>
#include <thread>
#include <unistd.h>

using namespace chip;
using StreamUsageEnum = chip::app::Clusters::Globals::StreamUsageEnum;

namespace camera {

namespace {

constexpr EndpointId kCameraEndpointId = 1;

} // namespace

void DeviceManager::VideoStreamSignalHandler(int sig)
{
    if (sig == SIGCHLD)
    {
        // Reap any terminated child processes
        pid_t pid;
        int status;

        while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
        {
            ChipLogProgress(Camera, "Video stream process (PID: %d) terminated", pid);
        }
    }
}

CHIP_ERROR DeviceManager::Init(Controller::DeviceCommissioner * commissioner)
{
    VerifyOrReturnError(commissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);
    mCommissioner = commissioner;
    mAVStreamManagment.Init(commissioner);

    // Register callback for WebRTC session establishment
    WebRTCManager::Instance().SetSessionEstablishedCallback(
        [this](uint16_t streamId) { this->OnWebRTCSessionEstablished(streamId); });

    return CHIP_NO_ERROR;
}

void DeviceManager::Shutdown()
{
    // Stop all video stream processes
    for (auto & pair : mVideoStreamProcesses)
    {
        StopVideoStreamProcess(pair.first);
    }
    mVideoStreamProcesses.clear();

    // Disconnect WebRTC session
    WebRTCManager::Instance().Disconnect();
}

CHIP_ERROR DeviceManager::AllocateVideoStream(NodeId nodeId, uint8_t streamUsage, WebRTCOfferType offerType,
                                              Optional<uint16_t> minWidth, Optional<uint16_t> minHeight,
                                              Optional<uint16_t> minFrameRate, Optional<uint32_t> minBitRate)
{
    ChipLogProgress(Camera, "Allocate a video stream on the camera device.");

    CHIP_ERROR error = mAVStreamManagment.AllocateVideoStream(nodeId, kCameraEndpointId, streamUsage, minWidth, minHeight,
                                                              minFrameRate, minBitRate);

    if (error != CHIP_NO_ERROR)
    {
        ChipLogError(Camera,
                     "Failed to send VideoStreamAllocate command to the camera device (NodeId: " ChipLogFormatX64
                     "). Error: %" CHIP_ERROR_FORMAT,
                     ChipLogValueX64(nodeId), error.Format());
    }
    else
    {
        mNodeId      = nodeId;
        mStreamUsage = streamUsage;
        mOfferType   = offerType;
    }

    return error;
}

CHIP_ERROR DeviceManager::DeallocateVideoStream(NodeId nodeId, uint16_t videoStreamId)
{
    ChipLogProgress(Camera, "Deallocate a video stream on the camera device.");

    CHIP_ERROR error = mAVStreamManagment.DeallocateVideoStream(nodeId, kCameraEndpointId, videoStreamId);

    if (error != CHIP_NO_ERROR)
    {
        ChipLogError(Camera,
                     "Failed to send VideoStreamDeallocate command to the camera device (NodeId: " ChipLogFormatX64
                     "). Error: %" CHIP_ERROR_FORMAT,
                     ChipLogValueX64(nodeId), error.Format());
    }
    else
    {
        // Stop the video stream process and disconnect WebRTC
        StopVideoStreamProcess(videoStreamId);
        WebRTCManager::Instance().Disconnect();
    }

    return error;
}

void DeviceManager::HandleAttributeData(const app::ConcreteDataAttributePath & path, TLV::TLVReader & data) {}

void DeviceManager::HandleEventData(const app::EventHeader & header, TLV::TLVReader & data) {}

void DeviceManager::HandleCommandResponse(const app::ConcreteCommandPath & path, TLV::TLVReader & data)
{
    ChipLogProgress(Camera, "Command Response received.");

    if (path.mClusterId == app::Clusters::CameraAvStreamManagement::Id &&
        path.mCommandId == app::Clusters::CameraAvStreamManagement::Commands::VideoStreamAllocateResponse::Id)
    {
        HandleVideoStreamAllocateResponse(data);
    }
}

void DeviceManager::StopVideoStream(uint16_t streamId)
{
    // Disconnect WebRTC session
    WebRTCManager::Instance().Disconnect();

    StopVideoStreamProcess(streamId);
}

void DeviceManager::HandleVideoStreamAllocateResponse(TLV::TLVReader & data)
{
    ChipLogProgress(Camera, "Handle VideoStreamAllocateResponse command.");

    app::Clusters::CameraAvStreamManagement::Commands::VideoStreamAllocateResponse::DecodableType value;
    CHIP_ERROR error = app::DataModel::Decode(data, value);

    if (error != CHIP_NO_ERROR)
    {
        ChipLogError(Camera, "Failed to decode command response value. Error: %" CHIP_ERROR_FORMAT, error.Format());
        return;
    }

    // Log all fields
    ChipLogProgress(Camera, "DecodableType fields:");
    ChipLogProgress(Camera, "  videoStreamId: %u", value.videoStreamID);

    // Store the stream ID we're setting up only for LiveView streams
    if (mStreamUsage == static_cast<uint8_t>(StreamUsageEnum::kLiveView))
    {
        mPendingVideoStreamId = value.videoStreamID;
    }

    InitiateWebRTCSession(value.videoStreamID);
}

void DeviceManager::InitiateWebRTCSession(uint16_t videoStreamId)
{
    ChipLogProgress(Camera, "DeviceManager: Initiating WebRTC session for node=0x" ChipLogFormatX64, ChipLogValueX64(mNodeId));

    // Connect to the WebRTC transport provider on the device
    CHIP_ERROR err = WebRTCManager::Instance().Connect(*mCommissioner, mNodeId, kCameraEndpointId);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Camera, "Failed to connect WebRTC manager. Error: %" CHIP_ERROR_FORMAT, err.Format());
        return;
    }

    // Add a 1-second delay after successful connection to allow local SDP gets populated
    std::this_thread::sleep_for(std::chrono::seconds(1));

    auto videoStreamIdNullable = app::DataModel::MakeNullable(videoStreamId);
    auto videoStreamIdOptional = MakeOptional(videoStreamIdNullable);
    auto streamUsage           = static_cast<StreamUsageEnum>(mStreamUsage);

    // Choose between ProvideOffer and SolicitOffer based on the configured offer type
    if (mOfferType == WebRTCOfferType::kProvideOffer)
    {
        ChipLogProgress(Camera, "Using ProvideOffer for WebRTC session establishment");
        err = WebRTCManager::Instance().ProvideOffer(app::DataModel::NullNullable, // session ID (null)
                                                     streamUsage,                  // stream‑usage field
                                                     videoStreamIdOptional,        // videoStreamId you just built
                                                     NullOptional);                // audioStreamID (empty)
    }
    else // WebRTCOfferType::kSolicitOffer
    {
        ChipLogProgress(Camera, "Using SolicitOffer for WebRTC session establishment");
        err = WebRTCManager::Instance().SolicitOffer(streamUsage,           // stream‑usage field
                                                     videoStreamIdOptional, // videoStreamId you just built
                                                     NullOptional);         // audioStreamID (empty)
    }

    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Camera, "Failed to initiate WebRTC offer. Error: %" CHIP_ERROR_FORMAT, err.Format());
    }
}

void DeviceManager::OnWebRTCSessionEstablished(uint16_t streamId)
{
    ChipLogProgress(Camera, "WebRTC session established for stream ID: %u", streamId);

    // Only start video stream process for LiveView streams
    if (mStreamUsage == static_cast<uint8_t>(StreamUsageEnum::kLiveView))
    {
        // Verify this matches our pending stream
        if (streamId == mPendingVideoStreamId)
        {
            StartVideoStreamProcess(streamId);
            mPendingVideoStreamId = 0;
        }
    }
}

void DeviceManager::StartVideoStreamProcess(uint16_t streamId)
{
    ChipLogProgress(Camera, "Starting video stream process for stream ID: %u", streamId);

    // Terminate any previous pipeline that was bound to this stream ID
    StopVideoStreamProcess(streamId);

    const uint16_t udpPort    = 5000;
    const std::string portStr = "port=" + std::to_string(udpPort);
    const char * const argv[] = { "gst-launch-1.0",
                                  "udpsrc",
                                  portStr.c_str(),
                                  "!",
                                  "application/x-rtp,media=video,clock-rate=90000,encoding-name=H264,payload=96",
                                  "!",
                                  "rtph264depay",
                                  "!",
                                  "queue",
                                  "!",
                                  "h264parse",
                                  "!",
                                  "avdec_h264",
                                  "!",
                                  "videoconvert",
                                  "!",
                                  "autovideosink",
                                  nullptr };

    // Fork process to run GStreamer pipeline
    pid_t pid = fork();
    if (pid == 0)
    {
        // Child process - execute GStreamer command
        // Put the pipeline in its own process group so we can kill it safely if needed.
        setpgid(0, 0);

        // Redirect stdout and stderr to /dev/null to suppress output
        freopen("/dev/null", "w", stdout);
        freopen("/dev/null", "w", stderr);

        // Replace the child with gst‑launch‑1.0 (only returns on error)
        execvp(argv[0], const_cast<char * const *>(argv));

        // If we got here execvp failed
        ChipLogError(Camera, "execvp(gst-launch-1.0) failed: %s", strerror(errno));
        _exit(EXIT_FAILURE);
    }
    else if (pid > 0)
    {
        // Parent process - store PID for later cleanup
        mVideoStreamProcesses[streamId] = pid; // Track the real gst‑launch PID
        ChipLogProgress(Camera, "Video stream process started with PID: %d", pid);
    }
    else
    {
        // Fork failed
        ChipLogError(Camera, "Failed to fork process for video stream. Error: %s", strerror(errno));
    }
}

void DeviceManager::StopVideoStreamProcess(uint16_t streamId)
{
    auto it = mVideoStreamProcesses.find(streamId);
    if (it != mVideoStreamProcesses.end())
    {
        pid_t pid = it->second;
        ChipLogProgress(Camera, "Stopping video stream process (PID: %d) for stream ID: %u", pid, streamId);

        // Send SIGTERM first for graceful shutdown
        if (kill(pid, SIGTERM) == 0)
        {
            // Wait for graceful shutdown (with timeout)
            int status;
            int waitResult = waitpid(pid, &status, WNOHANG);

            if (waitResult == 0)
            {
                // Process still running, wait a bit then force kill
                sleep(1);
                waitResult = waitpid(pid, &status, WNOHANG);

                if (waitResult == 0)
                {
                    ChipLogProgress(Camera, "Force killing video stream process (PID: %d)", pid);
                    kill(pid, SIGKILL);
                    waitpid(pid, &status, 0); // Wait for process to be reaped
                }
            }
        }
        else
        {
            ChipLogError(Camera, "Failed to send SIGTERM to process %d: %s", pid, strerror(errno));
        }

        mVideoStreamProcesses.erase(it);
    }
}

} // namespace camera
