<?php

declare(strict_types=1);

namespace App\Service\Pdf;

use TCPDF;

final class SalsabilTcpdf extends TCPDF
{
    /** @var array{school:string,title:string,logo:?string,reference:string,matricule:string,status:string,primary:array{0:int,1:int,2:int}} */
    private array $salsabilHeader = [
        'school' => 'SALSABIL Madrassas',
        'title' => 'Document administratif',
        'logo' => null,
        'reference' => '-',
        'matricule' => '-',
        'status' => '-',
        'primary' => [15, 92, 69],
    ];

    /** @var array{contacts:string,school:string,qr:string} */
    private array $salsabilFooter = [
        'contacts' => '',
        'school' => 'SALSABIL Madrassas',
        'qr' => 'SALSABIL Madrassas',
    ];

    public function __construct($orientation = 'P', $unit = 'mm', $format = 'A4', $unicode = true, $encoding = 'UTF-8', $diskcache = false, $pdfa = false)
    {
        parent::__construct($orientation, $unit, $format, $unicode, $encoding, $diskcache, $pdfa);
        $this->tcpdflink = false;
    }

    /**
     * @param array{0:int,1:int,2:int} $primary
     */
    public function setSalsabilHeaderContext(
        string $school,
        string $title,
        ?string $logoPath,
        ?string $reference,
        ?string $matricule,
        string $status,
        array $primary,
    ): void {
        $this->salsabilHeader = [
            'school' => $school,
            'title' => $title,
            'logo' => $logoPath,
            'reference' => $reference ?: '-',
            'matricule' => $matricule ?: '-',
            'status' => $status,
            'primary' => $primary,
        ];
    }

    public function setSalsabilFooterContext(string $contacts, string $school, string $qrPayload): void
    {
        $this->salsabilFooter = [
            'contacts' => $contacts,
            'school' => $school,
            'qr' => $qrPayload,
        ];
    }

    public function Header(): void
    {
        $primary = $this->salsabilHeader['primary'];

        $this->SetFillColor($primary[0], $primary[1], $primary[2]);
        $this->Rect(0, 0, 210, 36, 'F');

        $logoPath = $this->salsabilHeader['logo'];
        $logoX = 17.0;
        $logoY = 8.0;
        $logoW = 70.0;
        $logoH = 20.0;
        $this->SetDrawColor(90, 190, 215);
        $this->SetFillColor(255, 255, 255);
        $this->RoundedRect($logoX, $logoY, $logoW, $logoH, 3.6, '1111', 'DF');

        if ($logoPath && is_file($logoPath)) {
            $this->Image($logoPath, $logoX + 2, $logoY + 1.5, $logoW - 4, $logoH - 3, '', '', '', true, 300, '', false, false, 0, false);
        } else {
            $this->SetTextColor($primary[0], $primary[1], $primary[2]);
            $this->SetFont('dejavusans', 'B', 10.5);
            $this->SetXY($logoX + 4, $logoY + 5.4);
            $this->Cell($logoW - 8, 6, $this->short(mb_strtoupper($this->salsabilHeader['school']), 28), 0, 0, 'C');
        }

        $title = mb_strtoupper($this->salsabilHeader['title'], 'UTF-8');
        $this->SetTextColor(255, 255, 255);
        $this->fitCellText($title, 104, 13.2, 92, 9, 13.8, 'R', 'dejavusansmono');
    }

    public function Footer(): void
    {
        $primary = $this->salsabilHeader['primary'];
        $barY = 275.0;
        $barH = 22.0;

        $this->SetFillColor($primary[0], $primary[1], $primary[2]);
        $this->Rect(0, $barY, 210, $barH, 'F');
        $this->SetDrawColor(116, 122, 132);
        $this->Rect(0, $barY, 210, $barH, 'D');

        $this->SetTextColor(255, 255, 255);
        $this->SetFont('dejavusans', 'B', 7.2);
        $this->SetXY(14, $barY + 4.1);
        $this->MultiCell(56, 4, $this->salsabilFooter['contacts'], 0, 'L');

        $this->SetTextColor(255, 255, 255);
        $this->fitCellText(mb_strtoupper($this->salsabilFooter['school'], 'UTF-8'), 78, $barY + 5.1, 78, 7, 11.4, 'C', 'dejavusansmono');
        $this->SetFont('dejavusans', '', 5.2);
        $this->SetXY(78, $barY + 14.5);
        $this->Cell(78, 3, 'Document administratif - SALSABIL Madrassas', 0, 0, 'C');

        $qrBox = 24.0;
        $qrX = 175.0;
        $qrY = 264.4;
        $this->SetFillColor(255, 255, 255);
        $this->SetDrawColor($primary[0], $primary[1], $primary[2]);
        $this->SetLineWidth(0.35);
        $this->Rect($qrX, $qrY, $qrBox, $qrBox, 'DF');
        $this->write2DBarcode($this->salsabilFooter['qr'], 'QRCODE,H', $qrX + 3, $qrY + 3, $qrBox - 6, $qrBox - 6, [
            'border' => false,
            'padding' => 0,
            'fgcolor' => [30, 42, 56],
            'bgcolor' => false,
        ], 'N');

        $this->SetTextColor(255, 255, 255);
        $this->SetFont('dejavusans', '', 5.6);
        $this->SetXY($qrX, $barY + 17);
        $this->Cell($qrBox, 3, 'Page '.$this->getAliasNumPage().'/'.$this->getAliasNbPages(), 0, 0, 'C');
    }

    private function initials(string $name): string
    {
        $parts = preg_split('/\s+/', trim($name)) ?: [];
        $letters = '';
        foreach ($parts as $part) {
            if ($part !== '') {
                $letters .= mb_substr($part, 0, 1);
            }
            if (mb_strlen($letters) >= 2) {
                break;
            }
        }

        return mb_strtoupper($letters ?: 'M');
    }

    private function short(?string $value, int $length): string
    {
        $value = trim((string) $value);
        if ($value === '') {
            return '-';
        }

        return mb_strlen($value) > $length ? mb_substr($value, 0, $length - 1).'…' : $value;
    }

    private function fitCellText(string $text, float $x, float $y, float $w, float $h, float $maxFontSize, string $align, string $fontFamily = 'dejavusans'): void
    {
        $fontSize = $maxFontSize;
        do {
            $this->SetFont($fontFamily, 'B', $fontSize);
            $textWidth = $this->GetStringWidth($text);
            if ($textWidth <= $w || $fontSize <= 7.2) {
                break;
            }
            $fontSize -= 0.4;
        } while ($fontSize > 7.2);

        $this->SetXY($x, $y);
        $this->Cell($w, $h, $text, 0, 0, $align, false, '', 0, false, 'T', 'M');
    }
}
