<?php

namespace App\Development\Mercury;

use Illuminate\Http\Client\Request;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;

// Mercury tunnel microservice mock - GRE tunnel state, stats and lifecycle, keyed by cxid or endpoint IP.
class Routes
{
    // Live BGP session state (peers, prefixes, status) for a tunnel's cxid.
    public function socket_bgp(array $params, Request $request)
    {
        $responses = json_decode(file_get_contents(app_path('Development/Mercury/TunnelSocket.json')), true);

        if(!isset($responses['bgp'][Str::afterLast($request->url(), '/')])) {
            return Http::response([ 'Fallback Error' ], 500);
        }

        return Http::response(
            $responses['bgp'][Str::afterLast($request->url(), '/')]
        );
    }

    // Traffic peak / percentile stats for a tunnel's cxid.
    public function socket_peak(array $params, Request $request)
    {
        $responses = json_decode(file_get_contents(app_path('Development/Mercury/TunnelSocket.json')), true);

        if(!isset($responses['peak'][Str::afterLast($request->url(), '/')])) {
            return Http::response([ 'Fallback Error' ], 500);
        }

        return Http::response(
            $responses['peak'][Str::afterLast($request->url(), '/')]
        );
    }

    // Usage rollup used for a tunnel's billing, by cxid.
    public function socket_billing(array $params, Request $request)
    {
        $responses = json_decode(file_get_contents(app_path('Development/Mercury/TunnelSocket.json')), true);

        if(!isset($responses['bgp'][Str::afterLast($request->url(), '/')])) {
            return Http::response([ 'Fallback Error' ], 500);
        }

        return Http::response(
            $responses['billing'][Str::afterLast($request->url(), '/')]
        );
    }

    // The tunnels provisioned under a cxid.
    public function list_tunnels(array $params, Request $request)
    {
        $responses = json_decode(file_get_contents(app_path('Development/Mercury/TunnelList.json')), true);

        if(!isset($responses[Str::afterLast($request->url(), '/')])) {
            return Http::response([ 'Fallback Error' ], 500);
        }

        return Http::response(
            $responses[Str::afterLast($request->url(), '/')]
        );

    }

    /*
     * Provision a tunnel. Endpoint 103.1.1.1 is the fixture that succeeds; any other
     * endpoint IP returns a 409 to exercise the "endpoint already exists" conflict path.
     */
    public function create_tunnel(array $params, Request $request)
    {
        $responses = json_decode(file_get_contents(app_path('Development/Mercury/TunnelCreate.json')), true);

        if($params['endpoint_ip'] === '103.1.1.1') {

            if(!isset($responses['success'][$params['cxid']])) {
                return Http::response([ 'detail' => 'Server error' ], 500);
            }
            
            return Http::response( $responses['success'][$params['cxid']], 200 );            
        }

        return Http::response( $responses['failure'], 409 );
    }

    /*
     * A single tunnel addressed by its endpoint IP: fetch it (GET), update it (PUT),
     * or tear it down (DELETE).
     */
    public function by_endpoint(array $params, Request $request)
    {
        switch ($request->method()) {
            case 'GET':
                $responses = json_decode(file_get_contents(app_path('Development/Mercury/TunnelGet.json')), true);

                if(!isset($responses[Str::afterLast($request->url(), '/')])) {
                    return Http::response([ 'Fallback Error' ], 500);
                }

                return Http::response(
                    $responses[Str::afterLast($request->url(), '/')]
                );
            case 'PUT':
                return Http::response(json_decode(file_get_contents(app_path('Development/Mercury/TunnelUpdate.json')), true), 200);
            case 'DELETE':
                return Http::response(json_decode(file_get_contents(app_path('Development/Mercury/TunnelDelete.json')), true), 200);
        }

        return Http::response(['Fallback Error'], 500);
    }

}
