<?php

namespace App\Domains\Invoice\Actions\CreateInvoiceReceipt;

use App\Enumerations\InvoiceType;
use App\Models\PageText;
use App\Models\Tenant;
use App\Providers\PdfMergeProvider;
use App\Resources\InvoiceResource;
use Dompdf\Dompdf;
use Illuminate\Support\Facades\Storage;
use ZipArchive;

class CreateInvoiceReceiptCommand {
    private CreateInvoiceReceiptRequest $request;
    private string $tempDirectory;

    public function __construct(CreateInvoiceReceiptRequest $request) {
        $this->request = $request;
        $this->tempDirectory = Tenant::getTempDirectory();
    }

    public function execute() : CreateInvoiceReceiptResponse {
        $response = new CreateInvoiceReceiptResponse();

        $filename = $this->tempDirectory . $this->request->invoice->invoice_number . '.pdf';
        if (!Storage::exists($this->tempDirectory)) {
            Storage::makeDirectory(Tenant::getTempDirectory() . '/' . $this->tempDirectory);
        }

        $receipt = $this->request->invoice->document_filename;
        if ($receipt === null) {
            Storage::put(
                $filename,
                $this->createPdf( $this->createHtml(), 'portrait', $filename, false )
            );

            $response->fileName = $filename;
            return $response;
        }

        $token = (string)rand(1000000000, 9999999999);
        $pdf_data = $this->createPdf( $this->createHtml(), 'portrait', $filename, false );

        $tmpFileName = $this->tempDirectory . 'tmp-' . $token . '.pdf';
        Storage::put($tmpFileName, $pdf_data);

        try {
            $merger = new PdfMergeProvider();

            $merger
                ->add( storage_path('app/private/' . $tmpFileName ))
                ->add(storage_path('app/private/' . $receipt))
                ->merge(storage_path('app/private/' .$filename) );

            $response->fileName = $filename;
        } catch ( \Exception $e ) {
                $zip = new ZipArchive();
                $zip->open(
                    storage_path('app/private/' .$filename) . '.zip',
                    ZipArchive::CREATE | ZipArchive::OVERWRITE
                );
                $zip->addFile(storage_path('app/private/' . $tmpFileName ), 'antrag.pdf');
                $zip->addFile(storage_path('app/private/' . $receipt), 'beleg.pdf');

                $zip->close();
                $response->fileName = $filename . '.zip';


        } finally {
            Storage::delete($tmpFileName);
        }
        return $response;
    }



    private function createHtml() : string {


        $invoiceReadable = new InvoiceResource($this->request->invoice)->toArray();


        $travelPartTemplate = <<<HTML
            <tr><td>Reiseweg:</td><td>%1\$s</td></tr>
            <tr><td>Grund der Reise:</td><td>%6\$s</td></tr>
            <tr><td>Gesamtlänge der Strecke:</td><td>%2\$s km x %3\$s / km</td></tr>
            <tr><td>Materialtransport:</td><td>%4\$s</td></tr>
            <tr><td>Mitfahrende im PKW:</td><td>%5\$s</td></tr>
HTML;

        $flatTravelPart = sprintf(
        $travelPartTemplate,
        $invoiceReadable['travelDirection'] ,
        $invoiceReadable['distance'],
        $invoiceReadable['distanceAllowance'],
        $invoiceReadable['transportation'],
        $invoiceReadable['passengers'],
        $invoiceReadable['travelReason'] ,
        );

        $invoiceTravelPart = '<tr><td>Kosten für ÖPNV:</td><td>' . $invoiceReadable['amount'] . '</td></tr>';;
        $expensePart = '<tr><td>Auslagenerstattung:</td><td>' . $invoiceReadable['amount'] . '</td></tr>';

        $content = <<<HTML
            <html>
                <body style="margin-left: 20mm; margin-top: 17mm">
                    <h3>Abrechnungstyp %1\$s</h3><br /><br />


                    <table style="width: 100%%;">
                        <tr><td>Abrechnungsnummer:</td><td>%2\$s</td></tr>
                        <tr><td>Name:</td><td>%3\$s</td></tr>
                        <tr><td>E-Mail:</td><td>%4\$s</td></tr>
                        <tr><td>Telefon:</td><td>%5\$s</td></tr>
                        <tr><td>Anmerkungen:</td><td>%16\$s</td></tr>


                        <tr><td>Name der Kostenstelle:</td><td>%6\$s</td></tr>
                        <tr><td>Zahlungsgrund:</td><td>%7\$s</td></tr>
                        <tr><td>Wird der Betrag gespendet:</td><td>%8\$s</td></tr>
                        %9\$s
                        <tr style="font-weight: bold;">
                            <td style="border-bottom-width: 1px; border-bottom-style: double;">
                                Gesamtbetrag:
                            </td>
                            <td style="border-bottom-width: 1px; border-bottom-style: double;">
                                %10\$s
                            </td>
                        </tr>
                        <tr><td colspan="2"><br /><br /></td></tr>
                        %11\$s
                        <tr><td>Beleg digital eingereicht am:</td><td>%12\$s</td></tr>
                        <tr><td>Beleg akzeptiert am:</td><td>%13\$s</td></tr>
                        <tr><td>Beleg akzeptiert von:</td><td>%14\$s</td></tr>
                    </table>
                    %15\$s
                </body>
            </html>
HTML;

        switch ($this->request->invoice->type) {
            case InvoiceType::INVOICE_TYPE_TRAVELLING:
                $paymentType = $this->request->invoice->distance !== null ? $flatTravelPart : $invoiceTravelPart;
                break;
            default:
                $paymentType = $expensePart;
        }

        if ($this->request->invoice->donation) {
            $paymentInformation = '<tr><td colspan="2">' . PageText::where('name', 'CONFIRMATION_DONATE')->first()->content . '</td></tr>';
        } else {
            if ($this->request->invoice->contact_bank_iban === null) {
                $paymentInformation = '';
            } else {
                $paymentInformationTemplate = <<<HTML
                    <tr><td colspan="2">%1\$s</td></tr>
                    <tr><td>Kontoinhaber*in:</td><td>%2\$s</td></tr>
                    <tr><td>INAN:</td><td>%3\$s</td></tr>
                    <tr><td colspan="2"><br /><br /></td></tr>
HTML;

                $paymentInformation = sprintf(
                    $paymentInformationTemplate,
                    PageText::where('name', 'CONFIRMATION_PAYMENT')->first()->content,
                    $invoiceReadable['accountOwner'],
                    $invoiceReadable['accountIban']
                );
            }
        }

        $changes = $this->request->invoice->changes !== null ? '<p>' . $this->request->invoice->changes . '</p>' : '';


        return sprintf(
            $content,
            $invoiceReadable['invoiceTypeShort'],
            $invoiceReadable['invoiceNumber'],
            $invoiceReadable['contactName'],
            $invoiceReadable['contactEmail'],
            $invoiceReadable['contactPhone'],
            $invoiceReadable['costUnitName'],
            $invoiceReadable['invoiceType'],
            $invoiceReadable['donationText'],
            $paymentType,
            $invoiceReadable['amount'],
            $paymentInformation,
            $invoiceReadable['createdAt'],
            $invoiceReadable['approvedAt'],
            $invoiceReadable['approvedBy'],
            $changes,
            $invoiceReadable['comment'],
        );
    }

    private function createPdf( string $htmlfile, string $orientation, string $filename, bool $download = true ) {

        $dompdf = new Dompdf();
        $dompdf->loadHtml( $htmlfile, 'UTF-8' );
        $dompdf->setPaper( 'A4', $orientation );

        $dompdf->render();
        if ( ! $download ) {
            return $dompdf->output();
        }
        $dompdf->stream( $filename );
    }

}
