<?php

namespace App\Http\Controllers\Map;

use App\Http\Controllers\Controller;
use App\Models\map\Cable;
use App\Models\map\Cluster;
use App\Models\map\Fiber;
use App\Models\map\Tube;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class CableController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return Cable::get();
    }


    private function createCable(Request $request)
    {

        return Cable::create([
            "startNodeId" => $request->startNode["id"],
            "startNodeType" => $request->startNode["type"],
            "endNodeId" => $request->endNode["id"],
            "endNodeType" => $request->endNode["type"],

            "name" => $request->name,
            "coordinates" => json_encode($request->coordinates),
            "type" => "cable",
            "remarks" => $request->remarks,
            "cable_length" => $request->cable_length,
            "cable_distance" => $request->cable_distance,
            "fiber_count" => $request->fiber_count,
            "tube_count" => $request->tube_count,
            "cable_type" => $request->cable_type,
        ]);
    }
    public function createCableFibers(Cable $createdCable, Request $request)
    {


        for ($cable = 1; $cable <= $request->tube_count; $cable++) {
            $createdTube = Tube::create([
                "cable_id" => $createdCable->id,
                "tube_number" => $cable,
                "fiber_count" => $request->fiber_count,
            ]);

            for ($fiber = 1; $fiber <= $request->fiber_count; $fiber++) {
                Fiber::create([
                    "cable_id" => $createdCable->id,
                    "tube_id" => $createdTube->id,
                    "fiber_number" => $fiber,
                ]);
            }
        }

        return $createdCable->load("tubes.fibers");
    }


    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */

    public function store(Request $request)
    {
        $this->validate($request, [
            'startNode' => 'required',
            'endNode' => 'required',

            "name" => "required",
            "coordinates" => "required",
            "fiber_count" => "required",
            "tube_count" => "required",
            "cable_length" => "required",
            "cable_distance" => "required",
            "cable_type" => "in:tight-buffered,loose-tube-buffered",
        ]);

        $createdCable = $this->createCable($request);
        $this->createCableFibers($createdCable, $request);
        return $createdCable;
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Models\map\Cable  $cable
     * @return \Illuminate\Http\Response
     */
    public function show(Cable $cable)
    {
        return $cable->load("tubes.fibers");
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\map\Cable  $cable
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Cable $cable)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\map\Cable  $cable
     * @return \Illuminate\Http\Response
     */
    public function destroy(Cable $cable)
    {
        DB::beginTransaction();
        try {
            $loadedCable = $this->cableDetail($cable->id);
            foreach ($loadedCable->tubes as $tube) {
                foreach ($tube->fibers as $fiber) {
                    if ($fiber->parent_fiber_id || $fiber->child_fiber_id || $fiber->parent_component_type || $fiber->parent_component_id || $fiber->child_component_type || $fiber->child_component_id) {
                        throw new \Exception("Fiber is connected to a component");
                    }
                    $fiber->delete();
                }
                $tube->delete();
            }
            $loadedCable->delete();
            DB::commit();

            return [
                "message" => "Cable Deleted",
            ];
        } catch (\Throwable $th) {
            DB::rollBack();
            return Response()->json(
                [
                    "message" => $th->getMessage(),
                ],
                400
            );
        }
    }



    public function cableDetail($id)
    {
        $arr = [
            'tubes.fibers.parentComponent.device',
            'tubes.fibers.parentComponent.splitter',
            'tubes.fibers.childComponent.device',
            'tubes.fibers.childComponent.splitter',
            "tubes.fibers.parentFiber.cable:id,name",
            "tubes.fibers.childFiber.cable:id,name",
            "startNode",
            "endNode"
        ];
        try {
            $cable = Cable::with($arr)->find($id);
            return $cable;
        } catch (\Throwable $th) {
            return response()->json(["message" => $th->getMessage()], 400);
        }
    }

    public function connectFiber(Request $request)
    {
        $this->validate($request, [
            "upStreamFiberId" => "required",
            "downStreamFiberId" => "required",
        ]);

        $upStreamFiber  = Fiber::find($request->upStreamFiberId);
        $downStreamFiber  = Fiber::find($request->downStreamFiberId);

        $upStreamFiber->child_fiber_id = $downStreamFiber->id;
        $downStreamFiber->parent_fiber_id = $upStreamFiber->id;

        $upStreamFiber->save();
        $downStreamFiber->save();
        return [
            "message" => "Fiber Connected",
        ];
    }

    public function disconnectFiber(Fiber $fiber)
    {
        $loadedFiber = $fiber->load("childFiber", "childComponent");
        if ($loadedFiber->childComponent) {
            $loadedFiber->childComponent->fiber_id = null;
            $loadedFiber->childComponent->cable_id = null;
            $loadedFiber->childComponent->save();
        } else if ($loadedFiber->childFiber) {
            $loadedFiber->childFiber->parent_fiber_id = null;
            $loadedFiber->childFiber->save();
        } else {
            return response()->json(["message" => "Fiber not connected to any component"], 400);
        }

        $loadedFiber->child_fiber_id = null;
        $loadedFiber->child_component_type = null;
        $loadedFiber->child_component_id = null;
        $loadedFiber->save();

        return [
            "message" => "Fiber Disconnected",
        ];
    }
}
