<?php

namespace App\Http\Controllers\Map;

use App\Models\Client;
use App\Models\map\Cable;
use App\Models\Clientsinfo;
use App\Models\map\Cluster;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Controllers\ClientController;

class ClusterController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
        return Cluster::all("id", "type", "name", "coordinates", "isBox");
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create() {}

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $this->validate($request, [
            'name' => 'required',
            'coordinates' => 'required',
            "parent_type" => "nullable|in:cable",
            "parent_id" => "nullable|exists:cable_map,id",
            "parent_cluster" => "nullable|exists:cluster_map,id",
            "isBox" => "nullable"
        ]);

        $createdCluster = new Cluster();

        $createdCluster->parent_id = $request->parent_id;
        $createdCluster->parent_type = $request->parent_type;
        $createdCluster->parent_cluster = $request->parent_cluster;
        $createdCluster->name = $request->name;
        $createdCluster->coordinates = json_encode($request->coordinates);
        $createdCluster->remarks = $request->remarks;
        $createdCluster->isBox = $request->isBox;
        $createdCluster->type = "cluster";
        $createdCluster->save();

        return $createdCluster;
    }

    public function getUplink($cluster)
    {
        $upLinks = [];
        $currentId = $cluster->parent_id;
        $currentType = $cluster->parent_type;


        $loadFiled = ["id", "name", "type", "parent_id", "parent_type"];
        while ($currentId && $currentType) {
            if ($currentType == "cluster") {
                $currentNode = Cluster::find($currentId, $loadFiled);
            } else if ($currentType == "cable") {
                $currentNode = Cable::find($currentId, $loadFiled);
            }
            array_push($upLinks, $currentNode);
            $currentId = $currentNode->parent_id;
            $currentType = $currentNode->parent_type;
        }
        return array_reverse($upLinks);
    }


    public function show($cluster_id)
    {
        $clusterWith = [
            "devices",
            "splitters",
            "onus:id,name,serial_number,model,manufactures",
            "onus",
            "upStream",
            "downStream"
        ];
        $cluster = Cluster::with($clusterWith)->find($cluster_id);

        $cluster->clients = $this->getClusterClients($cluster->id);

        return $cluster;
    }

    public function getClusterClients(string $clusterId)
    {
        $cluster = Cluster::find($clusterId);
        $loadFiled = [
            "clientsinfo.id",
            "clientsinfo.box",
            "clientsinfo.client_id",
            "clientsinfo.clients_name",
            "clientsinfo.remarks",
            "clientsinfo.flat_no",
            "clientsinfo.building_name",
            "clientsinfo.road_no",
            "clientsinfo.area",
            "clientsinfo.contact_no",
            "clientsinfo.cable_type",
            "clientsinfo.client_latitude",
            "clientsinfo.client_longitude",
            "clientsinfo.connected_component_type",
            "clientsinfo.connected_component_id"
        ];


        $clients = Clientsinfo::with("client:userid,password,clients_status,id", "connectedComponent.device", "connectedComponent.splitter")->leftJoin("clients", "clients.id", "=", "clientsinfo.client_id")
            ->whereNull("clients.deleted_at")->where("clientsinfo.map_box_id", $cluster->id)->select($loadFiled)->get();

        $usersId = Client::whereIn('id', $clients->pluck('client_id'))->pluck('userid');

        $clientsOnlineInfo = ClientController::getClientsOnlineInfo($usersId);
        $clients = $clients->map(function ($client) use ($clientsOnlineInfo) {
            $client->status = $clientsOnlineInfo[$client->client->userid];
            return $client;
        });

        return $clients;
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Models\Cluster  $cluster
     * @return \Illuminate\Http\Response
     */
    public function edit(Cluster $cluster)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Cluster  $cluster
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Cluster $cluster)
    {
        $this->validate($request, [
            'name' => 'required',
            "isBox" => "nullable",
            "remarks" => "nullable"
        ]);

        $cluster->name = $request->name;
        $cluster->remarks = $request->remarks;
        $cluster->box = $request->box;
        $cluster->isBox = $request->isBox;

        $cluster->save();

        return $cluster;
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\Cluster  $cluster
     * @return \Illuminate\Http\Response
     */
    public function destroy($cluster_id)
    {
        $cluster = $this->show($cluster_id);

        $isClusterEmpty = sizeof($cluster->devices) !== 0 || sizeof($cluster->onus) !== 0 || sizeof($cluster->splitters) !== 0 || sizeof($cluster->upStream) !== 0 || sizeof($cluster->downStream) !== 0;

        if ($isClusterEmpty) {
            return response()->json(["message" => "Cluster is not empty"], 400);
        }

        $cluster->delete();
        return response()->json(["message" => "Cluster Deleted"], 200);
    }

    public function disconnectClient($client_id)
    {
        $client = Clientsinfo::with("connectedComponent")->find($client_id);
        if ($client->connectedComponent) {
            $client->connectedComponent->connected_component_type = null;
            $client->connectedComponent->connected_component_id = null;
            $client->connectedComponent->save();
        } else {
            return response()->json(["message" => "Client is not connected"], 400);
        }

        $client->connected_component_type = null;
        $client->connected_component_id = null;
        $client->save();
        return response()->json(["message" => "Client Disconnected"], 200);
    }

    public function getAllBoxes()
    {
        return Cluster::get(["id", "name"]);
    }

    public function getBoxCordinates($box_id)
    {
        return Cluster::find($box_id, ["coordinates"]);
    }
}
