<?php

namespace App\Modules\CardTransaction\Repositories;

use App\Modules\Card\Models\Card;
use App\Modules\Makeable;
use Exception;
use Filament\Notifications\Notification;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Livewire\Component;
use Mpdf\Mpdf;
use Mpdf\Output\Destination;

class CardTransactionRepository
{
    use Makeable;

    /**
     * Download card transaction
     *
     * @param  array<inst, string>|array{start_date: string, end_date: string}  $data
     */
    public function downloadCardTransaction(array $data, Card $record, Component $livewire): null
    {
        $start_date = new Carbon($data['start_date']);
        $end_date = new Carbon($data['end_date']);

        $apiResponse = $this->fetchApi(
            passport_serie: user()->passport_serie(),
            passport_id: user()->passport_id(),
            card_number_masked: Str::mask($record->number, '*', 6, 6),
            card_expire_date: $record->month.'/'.substr($record->year, 2),
            start_date: $start_date->format('d.m.Y'),
            end_date: $end_date->format('d.m.Y'),
        );

        /** @var \App\Modules\CardTransaction\Types\CardTransactionResponse */
        $response = Str::isJson($apiResponse)
                    ? json_decode($apiResponse)
                    : emptyClass(errCode: 1, message: 'Connection issue to VP');

        if ($response->errCode != 0) {
            Notification::make()
                ->danger()
                ->title($response->message)
                ->send();

            return null;
        }

        $url = $this->generateFileUrl($record, $response);

        // Tell Livewire to open it in a new tab
        $livewire->js("window.open('{$url}', '_blank')");

        return null;
    }

    /**
     * Fetch from internal API
     */
    public function fetchApi(
        string $passport_serie,
        string $passport_id,
        string $card_number_masked,
        string $card_expire_date,
        string $start_date,
        string $end_date
    ): string {
        try {
            $curl = curl_init();
            curl_setopt_array($curl, [
                CURLOPT_URL => 'http://10.3.158.102:9999/api/clientinfo/all',
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_ENCODING => '',
                CURLOPT_MAXREDIRS => 10,
                CURLOPT_TIMEOUT => 0,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
                CURLOPT_CUSTOMREQUEST => 'POST',
                CURLOPT_POSTFIELDS => sprintf('{ "idSeria": "%s", "idNo": "%s", "clientType": "recipient", "cardMaskNumber": "%s", "expDate": "%s", "fromDate" : "%s", "toDate" : "%s" }', $passport_serie, $passport_id, $card_number_masked, $card_expire_date, $start_date, $end_date),
                CURLOPT_HTTPHEADER => [
                    'Authorization: Basic dGJ1c2VyOlFBWndzeDEyMw==',
                    'Content-Type: application/json',
                ],
            ]);

            $response = curl_exec($curl);

            curl_close($curl);

            return (string) $response;
        } catch (Exception $e) {
            Log::error('AZAT API ERROR: '.$e->getMessage(), [
                'file' => $e->getFile(),
            ]);

            return 'CURL Error';
        }
    }

    /**
     * Handles all file stuff
     *
     * @param  \App\Modules\CardTransaction\Types\CardTransactionResponse  $response
     */
    public function generateFileUrl(Card $model, object $response): string
    {
        $unique_folder_name = Str::snake(str_replace(':', '-', now()->toDateTimeString()));
        $dir = public_path("files/{$unique_folder_name}");

        File::makeDirectory($dir, 0777, true, true);

        $fileDest = $dir."/{$model->id}.pdf";

        $this->generateFile($response, $fileDest);

        return url("files/{$unique_folder_name}/{$model->id}.pdf");
    }

    /**
     * Generate file
     *
     * @param  \App\Modules\CardTransaction\Types\CardTransactionResponse  $response
     */
    public function generateFile(object $response, string $fileDest): void
    {
        $mpdf = new Mpdf;

        // Write HTML content...
        $html = Blade::render('module.card-transaction::card-transaction-table', [
            'data' => $response,
            'extra' => $this->getExtraVariables($response),
        ]);

        $mpdf->WriteHTML($html);

        // Save the PDF to a file...
        $mpdf->Output($fileDest, Destination::FILE);
    }

    /**
     * @param  \App\Modules\CardTransaction\Types\CardTransactionResponse  $response
     */
    public function getExtraVariables(object $response): object
    {
        if (count($response->transactions) < 1) {
            return emptyClass(basdakyGalyndy: 0, ahyrkyGalyndy: 0, girdeji: 0, cykdajy: 0);
        }

        $basdakyGalyndy = $response->transactions[0]->rest;
        $basdakyTransaksiya = $response->transactions[0]->currOperSum;
        $sonkyGalyndy = $response->transactions[count($response->transactions) - 1]->rest;

        $positive = 0;
        $negative = 0;
        for ($i = 0; $i < count($response->transactions); $i++) {
            if ($response->transactions[$i]->sign == '-') {
                $negative += $response->transactions[$i]->currOperSum;
            } else {
                $positive += $response->transactions[$i]->currOperSum;
            }
        }

        return emptyClass(
            basdakyGalyndy: $basdakyGalyndy - ($basdakyTransaksiya),
            ahyrkyGalyndy: $sonkyGalyndy,
            girdeji: $positive,
            cykdajy: $negative
        );
    }
}
