<?php

namespace App\Services\Badges;

use FPDF;
use Illuminate\Http\Response;

class BadgePdfService
{
    public function __construct(
        protected BadgeUserLookupService $lookupService,
        protected BadgePrintLogService $printLogService,
        protected BadgeTextFormatter $formatter
    ) {
    }

    public function generate(
        array $userIds,
        ?string $schoolYear,
        array $rolesMap = [],
        array $classesMap = [],
        ?int $actorId = null
    ): Response {
        $userIds = $this->formatter->normalizeIds($userIds);

        $pdf = new FPDF('P', 'mm', 'A4');
        $pdf->SetAutoPageBreak(false);

        $badgeW = 95;
        $badgeH = 67;
        $marginL = 14;
        $marginT = 6;
        $gutterX = 0;
        $gutterY = 0;
        $cols = 2;
        $rows = 4;
        $perPage = $cols * $rows;

        $pagesAdded = 0;
        $i = 0;
        $seen = [];

        foreach ($userIds as $uid) {
            $info = $this->lookupService->getUserInfoById($uid, $schoolYear);

            if (!$info || !is_array($info)) {
                continue;
            }

            $userId = (int) ($info['user_id'] ?? $uid);
            $name = $this->formatter->norm($info['name'] ?? '');

            $postedRole = $rolesMap[$userId] ?? null;
            $roleResolved = $postedRole !== null
                ? $postedRole
                : $this->formatter->resolveRole($info);

            $roleResolved = $this->formatter->formatRole((string) $roleResolved);
            $info['role_resolved'] = $roleResolved;

            if (!empty($classesMap[$userId])) {
                $info['class_section_name'] = (string) $classesMap[$userId];
            }

            $class = $this->formatter->norm($info['class_section_name'] ?? '');

            $badgeKey = strtolower(trim($userId . '|' . $name . '|' . $roleResolved . '|' . $class));
            if (isset($seen[$badgeKey])) {
                continue;
            }
            $seen[$badgeKey] = true;

            if (($i % $perPage) === 0) {
                $pdf->AddPage();
                $pagesAdded++;
            }

            $indexOnPage = $i % $perPage;
            $row = intdiv($indexOnPage, $cols);
            $col = $indexOnPage % $cols;

            $x = $marginL + $col * ($badgeW + $gutterX);
            $y = $marginT + $row * ($badgeH + $gutterY);

            $this->drawBadgeInCell($pdf, $info, $x, $y, $badgeW, $badgeH, $schoolYear);
            $i++;
        }

        if ($pagesAdded === 0) {
            $pdf->AddPage();
            $pdf->SetFont('Arial', '', 10);
            $pdf->SetXY(10, 20);
            $pdf->MultiCell(0, 6, 'No valid staff selected or data not found.', 0, 'L');
        }

        $pdfString = $pdf->Output('S');

        $this->printLogService->logSafely(
            userIds: $userIds,
            actorId: $actorId,
            schoolYear: $schoolYear,
            rolesMap: $rolesMap,
            classesMap: $classesMap,
            copies: 1
        );

        return response($pdfString, 200, [
            'Content-Type' => 'application/pdf',
            'Content-Disposition' => 'inline; filename="Staff_Badges.pdf"',
        ]);
    }

    protected function drawBadgeInCell(FPDF $pdf, array $data, float $x, float $y, float $w, float $h, ?string $schoolYear): void
    {
        $pdf->SetFillColor(255, 255, 255);
        $pdf->Rect($x, $y, $w, $h, 'F');
        $pdf->SetDrawColor(200, 200, 200);
        $pdf->Rect($x, $y, $w, $h);

        $logoSize = 6;
        if (!empty($data['school_logo']) && file_exists($data['school_logo'])) {
            $pdf->Image($data['school_logo'], $x + $w - 6 - $logoSize, $y + 4, $logoSize + 3, $logoSize - 1);
        }
        if (!empty($data['isgl_logo']) && file_exists($data['isgl_logo'])) {
            $pdf->Image($data['isgl_logo'], $x + 4, $y + 4, $logoSize + 3, $logoSize - 1);
        }

        $padX = 4;
        $cursorY = $y + 4 + $logoSize + 2;

        $schoolName = strtoupper($this->formatter->norm($data['school_name'] ?? 'AL RAHMA SUNDAY SCHOOL'));
        $pdf->SetFont('Arial', '', 16);
        $pdf->SetXY($x + $padX, $cursorY);
        $pdf->MultiCell($w - 2 * $padX, 5, $this->formatter->toPdf($schoolName), 0, 'C');

        $pdf->Ln(9);
        $pdf->SetFont('Arial', 'B', 14);
        $pdf->SetX($x + $padX);
        $name = strtoupper($this->formatter->norm($data['name'] ?? 'STAFF'));
        $pdf->Cell($w - 2 * $padX, 6, $this->formatter->toPdf($name), 0, 1, 'C');

        $roleResolved = $this->formatter->norm((string) ($data['role_resolved'] ?? ''));
        if ($roleResolved === '') {
            $roleResolved = $this->formatter->resolveRole($data);
        }
        if ($roleResolved !== '') {
            $roleResolved = $this->formatter->formatRole($roleResolved);
        }

        $classRaw = $this->formatter->norm($data['class_section_name'] ?? '');
        $class = $this->formatter->formatClass($classRaw);

        $detectSrc = strtolower($this->formatter->norm(
            ($data['roles_raw'] ?? '') !== '' ? $data['roles_raw'] : (($data['role_name_raw'] ?? '') !== '' ? $data['role_name_raw'] : $roleResolved)
        ));
        $isTeacherish = str_contains($detectSrc, 'teacher') || preg_match('/\bta\b/', $detectSrc);

        if ($isTeacherish && $class !== '') {
            if (strtolower($class) === 'youth') {
                $display = 'Youth ' . $roleResolved;
            } elseif ($class === 'KG') {
                $display = 'KG ' . $roleResolved;
            } else {
                $display = 'Grade ' . $class . ' ' . $roleResolved;
            }
        } elseif ($roleResolved !== '') {
            $display = $roleResolved;
        } elseif ($class !== '') {
            $display = $class;
        } else {
            $display = 'STAFF';
        }

        $pdf->Ln(6);
        $pdf->SetFont('Arial', '', 14);
        $displayOut = $this->formatter->toPdf($display);
        $maxTextWidth = $w - 2 * $padX;
        $best = $this->formatter->fitText($pdf, $displayOut, 11, 7, $maxTextWidth);
        $pdf->SetFont('Arial', '', $best + 4);

        if ($pdf->GetStringWidth($displayOut) <= $maxTextWidth) {
            $pdf->SetX($x + $padX);
            $pdf->Cell($maxTextWidth, 5, $displayOut, 0, 1, 'C');
        } else {
            $pdf->SetX($x + $padX);
            $pdf->MultiCell($maxTextWidth, 5, $displayOut, 0, 'C');
        }

        $footerYear = $this->formatter->norm((string) ($schoolYear ?? ($data['school_year'] ?? '')));
        if ($footerYear !== '') {
            $pdf->SetFont('Arial', 'I', 14);
            $pdf->SetXY($x + $padX, $y + $h - 9);
            $pdf->Cell($w - 2 * $padX, 4, $this->formatter->toPdf($footerYear), 0, 0, 'C');
        }
    }
}