<?php

namespace Database\Seeders;

use App\Models\Asns;
use App\Models\Billing\BillingCommit;
use App\Models\Goliath\GoliathAppliance;
use App\Models\Goliath\GoliathMetro;
use App\Models\Goliath\GoliathRegion;
use App\Models\Goliath\GoliathSubregion;
use App\Models\Group;
use App\Models\GroupPermission;
use App\Models\Organisation;
use App\Models\OrganisationExternalIdentities;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;

class DevelopmentSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {

        // Setup two permission groups
        $group_admin = new Group(['name' => 'Creatia Standard User']);
        $group_user = new Group(['name' => 'Admin - Super']);

        $group_admin->save();
        $group_user->save();

        foreach([
            $group_admin->id => explode(' ', 'goliath.edit-chain=1 goliath.view=1 goliath.management=1 goliath.edit-flags=1 goliath.edit-prefix=1 goliath.l1.view=1 goliath.l1.edit=1 goliath.l1.log=1 goliath.l1.manage=1 goliath.l2.view=1 goliath.l2.edit=1 goliath.l2.log=1 goliath.l2.manage=1 network.subtenant=1 network.rename=1 network.delete=1 network.manage=1 network.map=1 mercury.view=0 mercury.delete=1 compute.bgp.view=1 compute.bgp.tier1=1 compute.bgp.tier2=1 compute.bgp.tier3=1 compute.bgp.write=1 compute.bgp.delete=1 billing.view=1 billing.chart=1 mercury.manage=1 network.redirect-view=1 network.redirect-write=1 goliath.l1.report=1 mitigation.attack.read=1 mitigation.attack.write=1 admin.mitigation.attack.read=1 admin.mitigation.attack.write=1 hook.view=1 hook.update=1 billing.admin.view=1 billing.admin.edit=1 provision.bgp.view=1 provision.bgp.write=1 goliath.l1.special=1 network.view=1 management.view=1 management.write=1 mitigation.view=1 mitigation.add=1 mitigation.edit=1 mitigation.management=1 mitigation.subtenancy=1 geoip.view=1 geoip.add=1 geoip.edit=1 geoip.management=1 geoip.subtenancy=1 mercury.v2.view=1 mercury.v2.add=1 mercury.v2.delete=1'),
            $group_user->id => explode(' ', 'goliath.l1.view=1 goliath.l1.log=1 goliath.l2.view=1 goliath.l2.log=1 goliath.l1.edit?gsl=1 goliath.heuristics.4?gsl=1 goliath.l2.edit?gsl=1 goliath.l1.edit:ddos-advanced=1 goliath.heuristics.4:ddos-advanced=1 goliath.l2.edit:ddos-advanced=1 network.rename=1 network.map=1 network.redirect-view=1 network.redirect-write=1 organisation.manage=1 goliath.l1.report=1 mitigation.attack.read=1 mitigation.attack.write=1 hook.view=1 hook.update=1 compute.bgp.view:bgp=1 compute.bgp.tier1:tier1=1 compute.bgp.tier2:tier2=1 compute.bgp.tier3:tier3=1 compute.bgp.write:bgp=1 compute.bgp.delete:bgp=1 network.delete=1 provision.bgp.view=1 provision.bgp.write=1 mercury.v2.view:mercury=1 mercury.v2.add:mercury=1 mercury.v2.delete:mercury=1 billing.view:billing=1 billing.chart:billing=1')
        ] as $id => $permissions) {

            foreach($permissions as $permission) {
                $pattern = '/^(?<permission>[^:?=]+)(?::(?<right>[^?=]+))?(?:\?(?<identifier>[^=]+))?(?:=(?<value>.+))?$/';

                preg_match($pattern, $permission, $matches);
;
                GroupPermission::create([
                    'group_id'          => $id,
                    'permission'        => $matches['permission'],
                    'conditional'       => $matches['right'] ?? null,
                    'identifier'        => $matches['identifier'] ?? null,
                    'status'            => $matches['value'] ?? 1
                ]);
            }

        }

        // Setup organisations
        $organisation_gsl = new Organisation(['name' => 'Global Secure Layer']);
        $organisation_a = new Organisation(['name' => 'Organisation A']);
        $organisation_b = new Organisation(['name' => 'Organisation B']);
        $organisation_c = new Organisation(['name' => 'Organisation C']);
        $organisation_d = new Organisation(['name' => 'Organisation D']);

        $organisation_gsl->save();
        $organisation_a->save();
        $organisation_b->save();
        $organisation_c->save();
        $organisation_d->save();

        // Setup a variety of ASNs
        $asn_gsl_1 = Asns::create([ 'asn' => 137409, 'organisation_id' => $organisation_gsl->id, 'approved' => 1 ]);
        $asn_gsl_2 = Asns::create([ 'asn' => 139284, 'organisation_id' => $organisation_gsl->id, 'approved' => 1 ]);
        $asn_a_1 = Asns::create([ 'asn' => 64496, 'organisation_id' => $organisation_a->id, 'approved' => 1 ]);
        $asn_b_1 = Asns::create([ 'asn' => 64497, 'organisation_id' => $organisation_b->id, 'approved' => 1 ]);
        $asn_c_1 = Asns::create([ 'asn' => 64498, 'organisation_id' => $organisation_c->id, 'approved' => 1 ]);
        $asn_d_1 = Asns::create([ 'asn' => 64499, 'organisation_id' => $organisation_d->id, 'approved' => 1 ]);
        $asn_d_2 = Asns::create([ 'asn' => 64500, 'organisation_id' => $organisation_d->id, 'approved' => 1 ]);

        // Setup a variety of users
        $user_gsl_1 = User::create([
            'name'              => 'Admin 1',
            'password'          => Hash::make('password'),
            'email'             => 'admin+a@globalsecurelayer.com',
            'group_id'          => $group_admin->id,
            'organisation_id'   => $organisation_gsl->id
        ]);

        $user_gsl_2 = User::create([
            'name'              => 'Admin 2',
            'password'          => Hash::make('password'),
            'email'             => 'admin+b@globalsecurelayer.com',
            'group_id'          => $group_admin->id,
            'organisation_id'   => $organisation_gsl->id
        ]);

        $user_gsl_3 = User::create([
            'name'              => 'Admin 3',
            'password'          => Hash::make('password'),
            'email'             => 'admin+c@globalsecurelayer.com',
            'group_id'          => $group_admin->id,
            'organisation_id'   => $organisation_gsl->id
        ]);

        $user_a_1 = User::create([
            'name'              => 'User A 1',
            'password'          => Hash::make('password'),
            'email'             => 'user+a-1@globalsecurelayer.com',
            'group_id'          => $group_user->id,
            'organisation_id'   => $organisation_a->id
        ]);

        $user_b_1 = User::create([
            'name'              => 'User B 1',
            'password'          => Hash::make('password'),
            'email'             => 'user+b-1@globalsecurelayer.com',
            'group_id'          => $group_user->id,
            'organisation_id'   => $organisation_b->id
        ]);

        $user_c_1 = User::create([
            'name'              => 'User C 1',
            'password'          => Hash::make('password'),
            'email'             => 'user+c-1@globalsecurelayer.com',
            'group_id'          => $group_user->id,
            'organisation_id'   => $organisation_c->id
        ]);

        $user_d_1 = User::create([
            'name'              => 'User D 1',
            'password'          => Hash::make('password'),
            'email'             => 'user+d-1@globalsecurelayer.com',
            'group_id'          => $group_user->id,
            'organisation_id'   => $organisation_d->id
        ]);

        $user_d_2 = User::create([
            'name'              => 'User D 2',
            'password'          => Hash::make('password'),
            'email'             => 'user+d-2@globalsecurelayer.com',
            'group_id'          => $group_user->id,
            'organisation_id'   => $organisation_d->id
        ]);

        $user_d_3 = User::create([
            'name'              => 'User D 3',
            'password'          => Hash::make('password'),
            'email'             => 'user+d-3@globalsecurelayer.com',
            'group_id'          => $group_user->id,
            'organisation_id'   => $organisation_d->id
        ]);

        OrganisationExternalIdentities::create([
            'identity' => 1,
            'key' => 'gsl',
            'organisation_id' => $organisation_gsl->id
        ]);

        OrganisationExternalIdentities::create([
            'identity' => 1,
            'key' => 'whmcs_godedicated',
            'organisation_id' => $organisation_gsl->id
        ]);

        OrganisationExternalIdentities::create([
            'identity' => 1,
            'key' => 'whmcs_streamline',
            'organisation_id' => $organisation_gsl->id
        ]);

        OrganisationExternalIdentities::create([
            'identity' => 2,
            'key' => 'gsl',
            'organisation_id' => $organisation_a->id
        ]);

        OrganisationExternalIdentities::create([
            'identity' => 3,
            'key' => 'gsl',
            'organisation_id' => $organisation_b->id
        ]);

        OrganisationExternalIdentities::create([
            'identity' => 4,
            'key' => 'whmcs_streamline',
            'organisation_id' => $organisation_c->id
        ]);

        OrganisationExternalIdentities::create([
            'identity' => 5,
            'key' => 'whmcs_godedicated',
            'organisation_id' => $organisation_d->id
        ]);

        // Billing commits for the GSL-brand orgs. client_id + service_id line up with the
        // billing directory mock and each org's 'gsl' external identity; effective_at starts
        // at the Dec 2025 launch so every selectable period has a commit. 1001 has two commits
        // to exercise the "latest effective commit" selection.
        foreach([
            [ 1, 1001, 'Global Secure Layer', 'IPT Australia',     '2025-12-01', 1,  1000, 0.15, 'USD', 'global' ],
            [ 1, 1001, 'Global Secure Layer', 'IPT Australia',     '2026-04-01', 1,  2000, 0.12, 'USD', 'global' ],
            [ 1, 1002, 'Global Secure Layer', 'IPT Singapore',     '2025-12-01', 15, 500,  0.20, 'USD', 'global' ],
            [ 1, 1003, 'Global Secure Layer', 'IPT United States', '2026-01-01', 1,  1000, 0.10, 'USD', 'global' ],

            [ 2, 2001, 'Organisation A',      'IPT Australia',     '2025-12-01', 1,  300,  0.18, 'AUD', 'australian' ],
            [ 2, 2002, 'Organisation A',      'IPT Europe',        '2025-12-01', 10, 200,  0.22, 'EUR', 'global' ],

            [ 3, 3001, 'Organisation B',      'IPT Australia',     '2025-12-01', 1,  500,  0.16, 'USD', 'global' ],
            [ 3, 3002, 'Organisation B',      'IPT Hong Kong',     '2026-02-01', 20, 250,  0.19, 'USD', 'global' ],
        ] as [$client, $service, $name, $service_name, $effective_at, $billing_day, $commit, $price, $currency, $method]) {
            BillingCommit::create([
                'whmcs_brand'       => 'gsl',
                'whmcs_client_id'   => $client,
                'whmcs_service_id'  => $service,
                'search_name'       => $name,
                'search_service'    => $service_name,
                'search_brand'      => 'GSL',
                'effective_at'      => $effective_at,
                'billing_day'       => $billing_day,
                'commit'            => $commit,
                'price_per_unit'    => $price,
                'currency'          => $currency,
                'method'            => $method,
            ]);
        }

        $region_north = GoliathRegion::create([ 'name' => 'North', 'telemetry_identifier' => 'N', 'visible' => 1 ]);
        $region_south = GoliathRegion::create([ 'name' => 'South', 'telemetry_identifier' => 'S', 'visible' => 1 ]);

        $subregion_northwest = GoliathSubregion::create([ 'name' => 'Northwest', 'telemetry_identifier' => 'NW', 'visible' => 1, 'region_id' => $region_north->id ]);
        $subregion_northeast = GoliathSubregion::create([ 'name' => 'Northeast', 'telemetry_identifier' => 'NE', 'visible' => 1, 'region_id' => $region_north->id ]);

        $subregion_southwest = GoliathSubregion::create([ 'name' => 'Southwest', 'telemetry_identifier' => 'SW', 'visible' => 1, 'region_id' => $region_south->id ]);
        $subregion_southeast = GoliathSubregion::create([ 'name' => 'Southeast', 'telemetry_identifier' => 'SE', 'visible' => 1, 'region_id' => $region_south->id ]);

        $datacentre_nw_1 = GoliathMetro::create([ 'name' => 'Northwest 1', 'telemetry_identifier' => 'NW1', 'visible' => 1, 'subregion_id' => $subregion_northwest->id ]);
        $datacentre_ne_1 = GoliathMetro::create([ 'name' => 'Northeast 1', 'telemetry_identifier' => 'NE1', 'visible' => 1, 'subregion_id' => $subregion_northeast->id ]);

        $datacentre_sw_1 = GoliathMetro::create([ 'name' => 'Southwest 1', 'telemetry_identifier' => 'SW1', 'visible' => 1, 'subregion_id' => $subregion_southwest->id ]);
        $datacentre_sw_2 = GoliathMetro::create([ 'name' => 'Southwest 2', 'telemetry_identifier' => 'SW2', 'visible' => 1, 'subregion_id' => $subregion_southwest->id ]);
        $datacentre_se_1 = GoliathMetro::create([ 'name' => 'Southeast 1', 'telemetry_identifier' => 'SE1', 'visible' => 1, 'subregion_id' => $subregion_southeast->id ]);
        $datacentre_se_2 = GoliathMetro::create([ 'name' => 'Southeast 2', 'telemetry_identifier' => 'SE2', 'visible' => 1, 'subregion_id' => $subregion_southeast->id ]);

        GoliathAppliance::create([
            'organisation_id' => $organisation_gsl->id,
            'region_id' => $region_north->id,
            'subregion_id' => $subregion_northwest->id,
            'metro_id' => $datacentre_nw_1->id,
            'name' => "GOL-NW-1-1",
            'address' => '10.100.' . rand(0, 255) . '.' . rand(0, 250)
        ]);

        GoliathAppliance::create([
            'organisation_id' => $organisation_gsl->id,
            'region_id' => $region_north->id,
            'subregion_id' => $subregion_northeast->id,
            'metro_id' => $datacentre_ne_1->id,
            'name' => "GOL-NE-1-1",
            'address' => '10.100.' . rand(0, 255) . '.' . rand(0, 250)
        ]);

        GoliathAppliance::create([
            'organisation_id' => $organisation_gsl->id,
            'region_id' => $region_south->id,
            'subregion_id' => $subregion_southwest->id,
            'metro_id' => $datacentre_sw_1->id,
            'name' => "GOL-SW-1-1",
            'address' => '10.100.' . rand(0, 255) . '.' . rand(0, 250)
        ]);

        GoliathAppliance::create([
            'organisation_id' => $organisation_gsl->id,
            'region_id' => $region_south->id,
            'subregion_id' => $subregion_southwest->id,
            'metro_id' => $datacentre_sw_1->id,
            'name' => "GOL-SW-1-2",
            'address' => '10.100.' . rand(0, 255) . '.' . rand(0, 250)
        ]);

        GoliathAppliance::create([
            'organisation_id' => $organisation_gsl->id,
            'region_id' => $region_south->id,
            'subregion_id' => $subregion_southwest->id,
            'metro_id' => $datacentre_sw_2->id,
            'name' => "GOL-SW-2-1",
            'address' => '10.100.' . rand(0, 255) . '.' . rand(0, 250)
        ]);

        GoliathAppliance::create([
            'organisation_id' => $organisation_gsl->id,
            'region_id' => $region_south->id,
            'subregion_id' => $subregion_southeast->id,
            'metro_id' => $datacentre_se_1->id,
            'name' => "GOL-SE-1-1",
            'address' => '10.100.' . rand(0, 255) . '.' . rand(0, 250)
        ]);

    }
}
