<?php

declare(strict_types=1);

namespace App\Services\Certificates;

class CertificatePdfService
{
    private string $fontDir;
    private string $imgDir;

    public function __construct()
    {
        $this->fontDir = public_path('assets/certificates/fonts') . DIRECTORY_SEPARATOR;
        $this->imgDir  = public_path('assets/certificates/images') . DIRECTORY_SEPARATOR;
    }

    /**
     * @param  array<array<string, mixed>>  $students
     */
    public function generate(array $students, string $certDate): string
    {
        $edwardianFont = \TCPDF_FONTS::addTTFfont($this->fontDir . 'Edwardian Script ITC Regular.ttf', 'TrueTypeUnicode', '', 32);
        $garamondBold  = \TCPDF_FONTS::addTTFfont($this->fontDir . 'Garamond Bold.ttf',                'TrueTypeUnicode', '', 32);
        $ebGaramond    = \TCPDF_FONTS::addTTFfont($this->fontDir . 'EBGaramond-Regular.ttf',           'TrueTypeUnicode', '', 32);

        $pdf = new \TCPDF('L', 'pt', 'A4', true, 'UTF-8', false);
        $pdf->SetCreator('Al Rahma Sunday School');
        $pdf->SetTitle('Student Certificates');
        $pdf->SetMargins(0, 0, 0, true);
        $pdf->SetAutoPageBreak(false, 0);
        $pdf->setPrintHeader(false);
        $pdf->setPrintFooter(false);
        $pdf->SetHeaderMargin(0);
        $pdf->SetFooterMargin(0);

        $W = $pdf->getPageWidth();
        $H = $pdf->getPageHeight();

        foreach ($students as $student) {
            $pdf->AddPage();
            $name  = $student['firstname'] . ' ' . $student['lastname'];
            $grade = $this->formatGrade((string) ($student['grade'] ?? ''));
            $certNumber = (string) ($student['cert_number'] ?? '');
            $verifyUrl = is_string($student['verify_url'] ?? null) ? $student['verify_url'] : null;

            $this->drawCertificate(
                $pdf,
                $W,
                $H,
                $name,
                $grade,
                $certDate,
                $certNumber,
                $verifyUrl,
                $edwardianFont,
                $garamondBold,
                $ebGaramond
            );
        }

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

    private function drawCertificate(
        \TCPDF $pdf,
        float  $W,
        float  $H,
        string $name,
        string $grade,
        string $certDate,
        string $certNumber,
        ?string $verifyUrl,
        string $edwardianFont,
        string $garamondBold,
        string $ebGaramond
    ): void {
        $pdf->Image($this->imgDir . 'title.png',      126, 0,   600);
        $pdf->Image($this->imgDir . 'background.png', 280, 176, 291, 340);
        $pdf->Image($this->imgDir . 'signature.png',  140, 410,  90,  80);

        $pdf->SetFont('times', 'B', 24);
        $pdf->SetTextColor(0, 0, 0);
        $pdf->SetXY(0, 151);
        $pdf->Cell($W, 24, 'Presented to:', 0, 0, 'C');

        if (! empty($verifyUrl)) {
            $style = [
                'border' => false,
                'padding' => 0,
                'fgcolor' => [0, 0, 0],
                'bgcolor' => false,
            ];
            $pdf->write2DBarcode($verifyUrl, 'QRCODE,L', 120, 162, 42, 42, $style, 'N');
        }

        $pdf->SetFont($edwardianFont, '', 38);
        $nameX = ($W - $pdf->GetStringWidth($name)) / 2;
        $this->drawGradientText($pdf, $edwardianFont, 38, $name, $nameX, 221.5);

        $pdf->SetFont('times', '', 20);
        $pdf->SetXY(0, 236);
        $pdf->Cell(600, 20, '___________________________________', 0, 0, 'R');

        $pdf->SetFont($ebGaramond, '', 20);
        $pdf->SetXY(0, 273);
        $pdf->Cell($W, 20, 'for successfully completing the requirements of', 0, 0, 'C');

        $pdf->SetFont($garamondBold, '', 20);
        $pdf->SetXY(0, 310);
        $pdf->Cell($W, 20, $grade, 0, 0, 'C');

        $pdf->SetFont('times', '', 20);
        $pdf->SetXY(0, 343);
        $pdf->Cell($W, 20, 'at', 0, 0, 'C');

        $pdf->SetFont($garamondBold, '', 20);
        $pdf->SetXY(0, 375);
        $pdf->Cell($W, 20, 'Al Rahma Sunday School', 0, 0, 'C');

        $this->drawGradientText($pdf, $edwardianFont, 26, $certDate, 586, 456);

        $pdf->SetFont('times', '', 20);
        $pdf->SetXY(0, 463);
        $pdf->Cell(742, 20, '_________________', 0, 0, 'R');
        $pdf->SetXY(650, 492);
        $pdf->Cell(80, 20, 'Date', 0, 0, 'C');

        $pdf->SetXY(106, 463);
        $pdf->Cell(200, 20, '_________________', 0, 0, 'L');
        $pdf->SetXY(106, 492);
        $pdf->Cell(168, 20, 'Signature', 0, 0, 'C');

        if ($certNumber !== '') {
            $pdf->SetFont('helvetica', '', 8);
            $pdf->SetTextColor(150, 150, 150);
            $pdf->SetXY(70.86, $H - 39.68);
            $pdf->Cell(200, 12, 'Certificate No. ' . $certNumber, 0, 0, 'L');
            $pdf->SetTextColor(0, 0, 0);
        }
    }

    private function drawGradientText(\TCPDF $pdf, string $fontName, float $fontSize, string $text, float $x, float $y): void
    {
        $pdf->SetFont($fontName, '', $fontSize);

        for ($i = 0; $i < 6; $i++) {
            $pdf->setAlpha(($i + 1) * 25 / 255);
            $pdf->SetTextColor(0, 0, 0);
            $pdf->Text($x + $i / 5, $y + $i / 5, $text);
        }

        $pdf->setAlpha(1);
        $pdf->SetTextColor(0, 0, 0);
        $pdf->Text($x, $y, $text);
    }

    private function formatGrade(string $raw): string
    {
        $clean = trim($raw);
        $lower = strtolower($clean);

        if (preg_match('/^\d+$/', $clean) && (int) $clean >= 1 && (int) $clean <= 9) {
            return 'Grade ' . $clean;
        }
        if ($lower === 'youth') {
            return 'Youth';
        }
        if ($lower === 'kg') {
            return 'Kindergarten';
        }

        return $clean;
    }
}
