<?php

namespace App\Repositories;

use App\Models\Source;
use Carbon\Carbon;
use GuzzleHttp\Exception\ConnectException;

class SourceRepository
{
    protected $source;
    protected $missing;
    protected $updated;
    protected $sources;

    public function __construct(Source $source)
    {
        $this->source  = $source;
        $this->missing = [];
        $this->updated = [];
        $this->sources = $source::where("active", true)->get();
    }

    public function getAll()
    {
        return $this->source::all();
    }

    public function get($id)
    {
        return $this->source::where("id", $id)->first();
    }

    public function getActive()
    {
        return $this->source::where("active", true)->get();
    }

    public function edit($request)
    {
        $source               = $this->get($request->id);
        $source->url          = $request->url;
        $source->type         = $request->type;
        $source->format       = $request->format;
        $source->active       = $request->status;
        $source->last_updated = Carbon::now();
        //token check
        if ($request->token != '' && $request->token != 'none') {
            $source->token = $request->token;
        } else {
            $source->token = '';
        }

        if ($source->save()) {
            return ['status' => true, 'message' => "Source Editited"];
        } else {
            return ['status' => false, 'message' => "Source Not Editited"];
        }
    }

    public function add($request)
    {
        $newSource = $this->source::create([
            'url'         => $request->url,
            'type'        => $request->type,
            'format'      => $request->format,
            'active'      => $request->status,
            'token'       => $request->token,
            'last_udated' => Carbon::now(),
        ]);

        if ($newSource) {
            return ['status' => true, 'message' => "New Source Created!"];
        } else {
            return ['status' => false, 'message' => "Uh oh, New Source Not Created!"];
        }
    }

    public function updateSourceData($index = 0)
    {
        //checks all the sources to refresh data
        $count = count($this->sources);
        if ($count == 0) {
            return [
                'checked'    => $this->updated,
                'notchecked' => $this->missing,
                'count'      => $count,
                'updated'    => 'false',
            ];
        } else {
            //check index
            if ($index <= $count - 1) {
                $source = $this->sources[$index];
                $result = $this->getMastoBlocklist($source);
                if (count($result) > 0) {
                    $source->list_data    = json_encode($result);
                    $source->last_updated = Carbon::now();
                    $source->save();
                    array_push($this->updated, ['source' => $source->url]);
                    $index++;
                    $result = $this->updateSourceData($index);
                } else {
                    //if empty run the same index again
                    array_push($this->missing, ['source' => $source->url]);
                    $result = $this->updateSourceData($index);
                }
            } else {
                //continue
            }
            return [
                'checked'    => $this->updated,
                'notchecked' => $this->missing,
                'count'      => $count,
                'updated'    => 'true',
            ];
        }
    }

    private function getMastoBlocklist($source)
    {
        $result = [];
        if ($source['type'] == 'mastodon') {
            if ($source['token'] == null) {
                try {
                    $result = \Mastodon::domain('https://' . $source['url'])
                        ->get('/instance/domain_blocks');
                } catch (ConnectException $e) {
                    //TODO: Logo Errors
                }
            } else {
                try {
                    $result = \Mastodon::domain('https://' . $source['url'])
                        ->token($source['token'])
                        ->get('/instance/domain_blocks');
                } catch (ConnectException $e) {
                    //TODO: Logo Errors
                }
            }
        } elseif ($source['type'] == 'custom' && $source['format'] == 'csv') {
            try {
                $denylist = array_map('str_getcsv', file('https://' . $source['url']));
                foreach ($denylist as $item) {
                    array_push($result, [
                        'domain'   => $item[0],
                        'severity' => $item[1],
                        'comment'  => $item[2]]);
                }
                array_push($checked, ['source' => $source->url]);
            } catch (Exception $e) {
                array_push($missing, ['source' => $source->url]);
            }
        }
        return $result;
    }
}
