<?php

namespace App\Http\Controllers\Map;

use App\Http\Controllers\Controller;
use App\Models\map\Splitter;
use App\Models\map\SplitterOut;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

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

    /**
     * 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|string",
            "cluster_id" => "required|integer",
            "split_ratio" => "required|integer"
        ]);

        $createdSplitter = Splitter::create([
            "name" => $request->name,
            "cluster_id" => $request->cluster_id,
            "split_ratio" => $request->split_ratio,
            "type" => "splitter"
        ]);

        for ($i = 1; $i <= $request->split_ratio; $i++)
            $createdSplitter->SplitterOut()->create(["out_number" => $i]);

        return $createdSplitter->load("splitterOut");
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Models\map\Splitter  $splitter
     * @return \Illuminate\Http\Response
     */
    public function show(Splitter $splitter)
    {

        return $splitter->load(
            "splitterOut.fiber:id,fiber_number,cable_id",
            "splitterOut.fiber.cable:id,name",
            "splitterOut.connectedComponent",
            "splitterOut.connectedComponent.client:userid,password,clients_status,id",
            "connectedComponent.splitter:name,id,split_ratio",
            "connectedComponent.device:name,id,type",
            "fiber.cable"
        );
    }

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

        $splitter->name = $request->name;
        $splitter->remarks = $request->remarks;
        $splitter->save();

        return $splitter->load("splitterOut");
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\map\Splitter  $splitter
     * @return \Illuminate\Http\Response
     */
    public function destroy(Splitter $splitter)
    {
        $loadedSplitter = $this->show($splitter);
        DB::beginTransaction();
        try {
            if ($loadedSplitter->connectedComponent || $loadedSplitter->fiber_id) {
                throw new \Exception("Splitter is connected to a component");
            }

            foreach ($loadedSplitter->splitterOut as $splitterOut) {
                if ($splitterOut->fiber_id || $splitterOut->connected_component_id || $splitterOut->connected_component_type) {
                    throw new \Exception("Splitter out is connected to a component");
                }
                $splitterOut->delete();
            }
            $loadedSplitter->delete();
            DB::commit();
            return response()->json([
                "message" => "Splitter deleted successfully"
            ], 200);
        } catch (\Throwable $th) {
            DB::rollBack();
            return response()->json([
                "message" => $th->getMessage()
            ], 400);
        }
    }

    public function disconnectParentComponent($splitter_id)
    {

        $splitter = Splitter::with("connectedComponent", "fiber", "splitterOut")->find($splitter_id);
        if ($splitter->connected_component_type && $splitter->connected_component_id) {
            $splitter->connectedComponent->connected_component_type = null;
            $splitter->connectedComponent->connected_component_id = null;
            $splitter->connectedComponent->save();
        } else if ($splitter->fiber_id) {
            $fiber = $splitter->fiber;
            if ($fiber->parent_component_type === $splitter->type && $fiber->parent_component_id === $splitter->id) {
                $fiber->parent_component_type = null;
                $fiber->parent_component_id = null;
            } else if ($fiber->child_component_type === $splitter->type && $fiber->child_component_id === $splitter->id) {
                $fiber->child_component_type = null;
                $fiber->child_component_id = null;
            } else {
                return response()->json([
                    "message" => "Fiber is not connected to this port"
                ], 400);
            }
            $fiber->child_component_type = null;
            $fiber->child_component_id = null;
            $fiber->save();
        }


        $splitter->connected_component_type = null;
        $splitter->connected_component_id = null;
        $splitter->fiber_id = null;
        $splitter->cable_id = null;

        $splitter->save();
        return Response()->json(
            [
                "message" => "Successfully disconnected"
            ],
            200
        );
    }

    public function disconnectChildComponent($splitterOutId)
    {
        $splitterOut = SplitterOut::with("connectedComponent", "fiber")->find($splitterOutId);

        if ($splitterOut->fiber_id) {
            $fiber = $splitterOut->fiber;
            if ($fiber->parent_component_type === $splitterOut->type && $fiber->parent_component_id === $splitterOut->id) {
                $fiber->parent_component_type = null;
                $fiber->parent_component_id = null;
            } else if ($fiber->child_component_type === $splitterOut->type && $fiber->child_component_id === $splitterOut->id) {
                $fiber->child_component_type = null;
                $fiber->child_component_id = null;
            } else {
                return response()->json([
                    "message" => "Fiber is not connected to this port"
                ], 400);
            }
            $fiber->child_component_type = null;
            $fiber->child_component_id = null;
            $fiber->save();
        } else if ($splitterOut->connected_component_type === "onu") {
            if ($splitterOut->connectedComponent->lan_connected_component_type === $splitterOut->type && $splitterOut->connectedComponent->lan_connected_component_id === $splitterOut->id) {
                $splitterOut->connectedComponent->lan_connected_component_type = null;
                $splitterOut->connectedComponent->lan_connected_component_id = null;
            } else if ($splitterOut->connectedComponent->optical_connected_component_type === $splitterOut->type &&       $splitterOut->connectedComponent->optical_connected_component_id === $splitterOut->id) {
                $splitterOut->connectedComponent->optical_connected_component_type = null;
                $splitterOut->connectedComponent->optical_connected_component_id = null;
            } else {
                return response()->json([
                    "message" => "Onu is not connected to this splitter"
                ], 400);
            }
            $splitterOut->connectedComponent->save();
        } else if ($splitterOut->connected_component_type === "splitter" || $splitterOut->connected_component_type === "client") {
            $splitterOut->connectedComponent->connected_component_type = null;
            $splitterOut->connectedComponent->connected_component_id = null;
            $splitterOut->connectedComponent->save();
        } else {
            return response()->json([
                "message" => "Splitter out is not connected to any component"
            ], 400);
        }

        $splitterOut->connected_component_type = null;
        $splitterOut->connected_component_id = null;
        $splitterOut->fiber_id = null;
        $splitterOut->cable_id = null;
        $splitterOut->save();

        return response()->json([
            "message" => "Splitter disconnected successfully"
        ], 200);
    }
}
