<?php

namespace App\Services\Legal;

use App\Console\Commands\PruneDormantAccounts;
use App\Console\Commands\PruneUnverifiedAccounts;
use App\Support\CompanyProfile;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\View;
use TCPDF;

/**
 * The processing agreement and its annex, as PDFs.
 *
 * TCPDF, because the invoices already render through it — a second PDF engine
 * for two documents a year would be a dependency nobody maintains. Its HTML
 * support is not a browser's, so the two Blade views are deliberately plain:
 * headings, paragraphs, lists, one table.
 *
 * ## The documents are generated, not uploaded
 *
 * They name the company from CompanyProfile and take their deadlines from the
 * commands that enforce them, so the agreement cannot drift from the invoices or
 * from what the software actually does. An operator can still upload a lawyer's
 * revision as a new version — the console does not care where a file came from.
 */
final class DpaRenderer
{
    /**
     * The sub-processors this installation actually talks to.
     *
     * Here rather than in the template because it is a fact about the system,
     * not wording: hosting, payment and mail are the three places customer-
     * related data leaves this application, and a list that quietly omits one is
     * the single most common defect in a processing agreement.
     *
     * @return array<int, array<string, string>>
     */
    public static function subprocessors(): array
    {
        return [
            [
                'name' => 'Hetzner Online GmbH',
                'service' => 'Rechenzentrum, Server und Netzanbindung der Kundeninstanzen',
                'location' => 'Falkenstein und Nürnberg, Deutschland; Helsinki, Finnland',
            ],
            [
                'name' => 'Stripe Payments Europe, Ltd.',
                'service' => 'Zahlungsabwicklung (Vertrags- und Zahlungsdaten des Kunden, keine Instanzinhalte)',
                'location' => 'Irland (EU)',
            ],
            [
                'name' => 'thinkidoo e.U.',
                'service' => 'Mailserver für den Versand und Empfang der Betriebs- und Support-E-Mails',
                'location' => 'Österreich',
            ],
        ];
    }

    /** The agreement itself. */
    public function agreement(string $version, ?Carbon $issuedOn = null): string
    {
        return $this->render('legal.dpa.agreement', $version, $issuedOn, [
            'subprocessors' => self::subprocessors(),
        ]);
    }

    /** Annex 1: the technical and organisational measures. */
    public function measures(string $version, ?Carbon $issuedOn = null): string
    {
        return $this->render('legal.dpa.measures', $version, $issuedOn, [
            // From the commands that enforce them, so the document cannot
            // promise one deadline while the sweep runs another.
            'unverifiedDays' => PruneUnverifiedAccounts::AFTER_DAYS,
            'warnDays' => PruneDormantAccounts::WARN_DAYS_BEFORE,
        ]);
    }

    /** @param array<string, mixed> $data */
    private function render(string $view, string $version, ?Carbon $issuedOn, array $data): string
    {
        $issuedOn ??= now();

        $html = View::make($view, array_merge($data, [
            'version' => $version,
            // R19: written on the wall clock, because a date on a contract is
            // read by a person and not by a server.
            'issuedOn' => $issuedOn->local()->isoFormat('LL'),
        ]))->render();

        $pdf = new TCPDF('P', 'mm', 'A4', true, 'UTF-8');
        $pdf->SetCreator('CluPilot');
        $pdf->SetAuthor((string) (CompanyProfile::get('name') ?? 'CluPilot'));
        $pdf->SetTitle(__('dpa.title').' '.$version);
        // No default header or footer bar: this is a contract, not a report, and
        // TCPDF's default header prints a black line and a title nobody set.
        $pdf->setPrintHeader(false);
        $pdf->setPrintFooter(true);
        $pdf->SetMargins(20, 18, 20);
        $pdf->SetAutoPageBreak(true, 20);
        // DejaVu, because the text is German: TCPDF's core fonts have no ß in
        // the encoding this uses and would print it as a blank.
        $pdf->SetFont('dejavusans', '', 9.5);
        $pdf->AddPage();
        $pdf->writeHTML($html, true, false, true, false, '');

        return (string) $pdf->Output('', 'S');
    }
}
