<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\JsonResponse;
use Illuminate\Validation\Rule;
use App\Models\SendingDomain;
use App\Http\Helper\Helper;
use Illuminate\View\View;
use ZipArchive;
use Auth;

class SendingDomainController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(): View
    {
        Helper::checkPermissions('sending_domains');
        $page = "sending_domains";
        $page_title = __('app.sending_domains');
        $breadcrumbs = [
            __('app.sending_domains') => route('sending_domains.index'),
            __('app.manage') => '#'
        ];
        $groups = \App\Models\Group::groups(config('custom.group_sending_domains'));
        return view('sending_domains.index',compact('page', 'page_title', 'breadcrumbs', 'groups'));
    }

    /**
       * Retrun JSON datatable data
    */
    public function getSendingDomains(Request $request): Void
    {
        $result = SendingDomain::join('groups', 'groups.id', '=', 'sending_domains.group_id')
        ->select('sending_domains.id', 'sending_domains.domain', 'sending_domains.is_active', 'sending_domains.is_verified_key', 'sending_domains.is_verified_spf', 'sending_domains.is_verified_dmarc', 'sending_domains.created_at','groups.id as group_id', 'groups.name as group_name')
            ->app();

        $columns = ['sending_domains.id', 'sending_domains.id', 'sending_domains.domain', 'groups.name', 'sending_domains.is_active', 'sending_domains.is_verified_key', 'sending_domains.is_verified_spf', 'sending_domains.is_verified_dmarc', 'sending_domains.created_at'];

        $data = Helper::dataFilters($request, $result, $columns);

        $result = $data['result'];
        $sending_domains = $result->get();

        $data =  Helper::datatableTotals($data['total']);

        foreach($sending_domains as $sending_domain) {
            $checkbox = "<input type=\"checkbox\" value=\"{$sending_domain->id}\" class=\"form-check-input\">";

            $actions = '<div class="btn-sending_domain">';
            $actions .= '<button type="button" class="btn btn-outline-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">'.__('app.actions').'</button>';
            $actions .= '<ul class="dropdown-menu" style="">';
            $actions.= '<li><a class="dropdown-item" href="'.route('sending_domains.show', $sending_domain->id).'"><i class="bi bi-pencil"></i> '.__('app.edit').'</a></li>';
            $actions .= '<li><a class="dropdown-item" href="javascript:;" onclick="domainVerifications(\''.$sending_domain->id.'\', \'all\')"><i class="bi bi-check-lg"></i> '.__('app.verify_dns_entries').'</a></li>';
            $actions .= '<li><a class="dropdown-item" href="javascript:;" onclick="domainVerifications(\''.$sending_domain->id.'\', \'dkim\')"><i class="bi bi-check-lg"></i> '.__('app.verify_dkim').'</a></li>';
            $actions .= '<li><a class="dropdown-item" href="javascript:;" onclick="domainVerifications(\''.$sending_domain->id.'\', \'spf\')"><i class="bi bi-check-lg"></i> '.__('app.verify_spf').'</a></li>';
            $actions .= '<li><a class="dropdown-item" href="javascript:;" onclick="domainVerifications(\''.$sending_domain->id.'\', \'dmarc\')"><i class="bi bi-check-lg"></i> '.__('app.verify_dmarc').'</a></li>';
            $actions .= '<li><a class="dropdown-item"  href="'.route('download.keys', [$sending_domain->id]).'"><i class="bi bi-download"></i> '.__('app.download_keys').'</a></li>';
            $actions .= '<li><a class="dropdown-item text-danger" href="javascript:;" onclick="destroy(\''.$sending_domain->id.'\', \''.route('sending_domains.destroy', $sending_domain->id).'\')"><i class="bi bi-trash"></i> '.__('app.delete').'</a></li>';
            $actions .= '</ul>';

            $status = $sending_domain->is_active 
                ? "<span class='badge bg-success-gradient'>".__('app.yes')."</small>"
                : "<span class='badge bg-danger-gradient'>".__('app.no')."</small>";
            $dkim_verfied = $sending_domain->is_verified_key
                ? "<span class='badge bg-success-gradient'><i class='bi bi-check-lg'></i></small>"
                : "<span class='badge bg-danger-gradient'><i class='bi bi-x-lg'></i></small>";
            $spf_verfied = $sending_domain->is_verified_spf
                ? "<span class='badge bg-success-gradient'><i class='bi bi-check-lg'></i></small>"
                : "<span class='badge bg-danger-gradient'><i class='bi bi-x-lg'></i></small>";
            $dmarc_verfied = $sending_domain->is_verified_dmarc
                ? "<span class='badge bg-success-gradient'><i class='bi bi-check-lg'></i></small>"
                : "<span class='badge bg-danger-gradient'><i class='bi bi-x-lg'></i></small>";

            $group_name = "<span id='{$sending_domain->group_id}'>$sending_domain->group_name<span>";



            $data['data'][] = [
            "DT_RowId" => "row_{$sending_domain->id}",
            $checkbox,
            $sending_domain->id,
            $sending_domain->domain,
            $group_name,
            $status,
            "<span id='key-{$sending_domain->id}'>{$dkim_verfied}</span>",
            "<span id='spf-{$sending_domain->id}'>{$spf_verfied}</span>",
            "<span id='dmarc-{$sending_domain->id}'>{$dmarc_verfied}</span>",
            Helper::datetimeDisplay($sending_domain->created_at),
            $actions
            ];
        }
        echo json_encode($data);
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create(): View
    {
        Helper::checkPermissions('sending_domains');
        $groups = \App\Models\Group::groups(config('custom.group_sending_domains'));
        return view('sending_domains.create',compact('groups'));
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request): RedirectResponse
    {
        $request->validate([
            'domain' => [
                'required', 
                'regex:/^([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/',
                Rule::unique('sending_domains')->where(function ($query) use ($request) {
                    return $query->where('app_id', Auth::user()->app_id);
                }),
            ],
            'group_id' => 'required|integer',
        ]);

        $data = $this->_sendingDomainData($request);

        $keys = Helper::generateKeys();
        $data['public_key']  = $keys['public_key'];
        $data['private_key'] = $keys['private_key'];
        $data['host_dkim']   = "dkim._domainkey.".$data['domain'];
        $data['value_dkim']  = "v=DKIM1; k=rsa; p=".str_replace(['-----BEGINPUBLICKEY-----', '-----ENDPUBLICKEY-----'], ['', ''], $data['public_key']);
        $data['host_spf']    = $data['domain'];
        $data['value_spf']   = "v=spf1 mx ip4:".$_SERVER['SERVER_ADDR']." ~all";
        $data['host_dmarc']  = "_dmarc.".$data['domain'];
        $data['value_dmarc'] = "v=DMARC1; p=none;";

        $sending_domain = SendingDomain::create($data);

        activity('create')->withProperties(['app_id' => Auth::user()->app_id])->log(__('app.sending_domain') . " ({$request->domain}) ". __('app.log_create'));

        return redirect()->route('sending_domains.show', $sending_domain->id)
            ->with('success', $request->domain . ' ' . __('app.log_create'));
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\SendingDomain  $sending_domain
     * @return \Illuminate\Http\Response
     */
    public function show(SendingDomain $sending_domain): View
    {        
        Helper::checkPermissions('sending_domains');
        $page = 'sending_domains';
        $page_title = __('app.detail');
        $breadcrumbs = [
            __('app.sending_domain') => route('sending_domains.index'),
            __('app.detail') => '#'
        ];
        $groups = \App\Models\Group::groups(config('custom.group_sending_domains'));
        return view('sending_domains.detail')->with(compact('page', 'page_title', 'breadcrumbs', 'sending_domain', 'groups'));
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, SendingDomain $sending_domain): RedirectResponse
    {
        $data = $this->_sendingDomainData($request);
        $sending_domain->fill($data)->save();

        activity('create')->withProperties(['app_id' => Auth::user()->app_id])->log(__('app.sending_domain') . " ({$request->domain}) ". __('app.log_update'));

        return redirect()->back()
            ->with('success', __('app.sending_domain') . ' ' . __('app.log_update'));
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(int $id, Request $request): JsonResponse
    {
        if(!empty($request->action)) {
          $ids = array_values($request->ids);
          $domains = json_encode(array_values(SendingDomain::whereIn('id', $ids)->pluck('domain')->toArray()));
          $destroy = SendingDomain::whereIn('id', $ids)->delete();
        } else {
          $domains = SendingDomain::whereId($id)->value('domain');
          $destroy = SendingDomain::destroy($id);
        }
        
        activity('delete')->withProperties(['app_id' => Auth::user()->app_id])->log(__('app.sending_domain') . " ({$domains}) ". __('app.log_delete'));

        $data = [
            'success' => true,
            'message' => __('app.deleted_successfully')
        ];

        return response()->json($data, 200); 
    }

    /**
    * Retrun data for store or update
    */
    private function _sendingDomainData($request): Array
    {
        $input = $request->except('_token');
        $input['user_id'] = Auth::user()->id;
        $input['app_id'] = Auth::user()->app_id;
        return $input;
    }

    /**
    * Download sending domain public and private keys
    */
    public function downloadKeys($id)
    {
        Helper::checkPermissions('sending_domains');
        $sending_domain = SendingDomain::select('domain', 'public_key', 'private_key')->where('id', $id)->app()->first();

        $path_downloads = str_replace('[user-id]', Auth::user()->id, config('custom.path_downloads'));
        Helper::dirCreateOrExist($path_downloads); // create dir if not exist

        $public_key_file = $path_downloads.'public_key.txt';
        $private_key_file = $path_downloads.'private_key.txt';

        \File::put($public_key_file, $sending_domain->public_key);
        \File::put($private_key_file, $sending_domain->private_key);

        $zip_path = $path_downloads.$sending_domain->domain.'.zip';

        Helper::createZipFile($zip_path, $public_key_file, 'public_key.txt');
        Helper::createZipFile($zip_path, $private_key_file, 'private_key.txt');

        \File::delete($public_key_file);
        \File::delete($private_key_file);

        activity('download')->withProperties(['app_id' => Auth::user()->app_id])->log(__('app.sending_domain') . " ({$sending_domain->domain}) ". __('app.log_download_keys'));

        return response()->download($zip_path);
    }

    /**
    * Return after verify domain and tracking
    */
    public function domainVerifications($id, $type)
    {
        if($type == 'tracking') {
            $tracking  = false;
            $tracking_domain = \App\Models\TrackingDomain::findOrFail($id);
            $tracking = Helper::verifyTracking($tracking_domain);
            $result = [
              'tracking' => $tracking
            ];
            return json_encode($result);
        }

        $sending_domain = SendingDomain::findOrFail($id);

        $key = $spf = $dmarc = false;

        if($type == 'all' || $type == 'dkim') {
          $key = Helper::verifyDKIM($sending_domain);
        }

        if($type == 'all' || $type == 'spf') {
          // 2 sec delay to get dns entries angain
          sleep(2);
          $spf = Helper::verifySPF($sending_domain);
        }

        if($type == 'all' || $type == 'dmarc') {
          // 2 sec delay to get dns entries angain
          sleep(2);
          $dmarc = Helper::verifyDMARC($sending_domain);
        }

        $result = [
          'key' => $key,
          'spf' => $spf,
          'dmarc' => $dmarc
        ];
        return json_encode($result);
    }

}
