<?php

namespace App\Services\Whatsapp;

use App\Models\WhatsappInviteLog;
use App\Services\EmailService;
use Illuminate\Support\Facades\Log;

class WhatsappInviteEmailService
{
    public function __construct(private EmailService $emailService)
    {
    }

    public function send(array $payload): array
    {
        $to = array_values(array_unique(array_filter((array) ($payload['to_emails'] ?? []))));
        $cc = array_values(array_unique(array_filter((array) ($payload['cc_emails'] ?? []))));
        $cc = array_values(array_diff($cc, $to));

        if (empty($to) && !empty($cc)) {
            $to = $cc;
            $cc = [];
        }
        if (empty($to)) {
            Log::warning('WhatsappInvite: no recipients after normalization.');
            return ['ok' => false, 'message' => 'No recipients provided.'];
        }

        $sections = (array) ($payload['sections'] ?? []);
        $links = array_values(array_unique(array_filter((array) ($payload['links'] ?? []))));
        $parent = $payload['parent'] ?? null;
        $schoolYear = $payload['schoolYear'] ?? null;
        $semester = $payload['semester'] ?? null;

        $items = $this->buildItems($sections, $links);
        if (empty($items)) {
            Log::warning('WhatsappInvite: no invite items built.');
            return ['ok' => false, 'message' => 'No invite links found.'];
        }

        $subject = count($items) > 1
            ? 'Your WhatsApp Group Links (Multiple Classes)'
            : 'Your WhatsApp Group Link';

        $viewData = [
            'parent' => $parent,
            'items' => $items,
            'sections' => $sections,
            'links' => $links,
            'schoolYear' => $schoolYear,
            'semester' => $semester,
            'title' => $subject,
            'teacherNames' => $payload['teachers'] ?? [],
        ];

        $bodyHtml = '';
        try {
            $bodyHtml = view('emails/whatsapp_invite', $viewData, ['saveData' => true]);
        } catch (\Throwable $e) {
            $lines = ['Assalamu Alaikum,', '', 'Here are your WhatsApp link(s):'];
            foreach ($items as $it) {
                $lines[] = ' - ' . $it['class_section_name'] . ': ' . $it['invite_link'];
            }
            $lines[] = '';
            $lines[] = 'Jazakumu-llahu khayran.';
            $bodyHtml = nl2br(implode("\n", $lines));
        }

        $ok = $this->emailService->send($to, $subject, $bodyHtml, 'notifications', $cc);

        $singleSectionId = count($items) === 1
            ? ((int) ($items[0]['class_section_id'] ?? 0) ?: null)
            : null;
        $parentId = (int) ($parent['id'] ?? 0);

        if ($ok) {
            WhatsappInviteLog::logSuccess($parentId, implode(', ', $to), $singleSectionId, null);
            Log::info('Whatsapp invite sent.', ['to' => $to, 'cc' => $cc]);
        } else {
            WhatsappInviteLog::logFailure($parentId, implode(', ', $to), 'Email send failed', $singleSectionId, null);
            Log::error('Whatsapp invite failed.', ['to' => $to, 'cc' => $cc]);
        }

        return [
            'ok' => $ok,
            'recipients' => count($to),
        ];
    }

    private function buildItems(array $sections, array $links): array
    {
        $seen = [];
        $items = [];

        foreach ($sections as $section) {
            $sid = isset($section['class_section_id']) ? (int) $section['class_section_id'] : 0;
            $name = trim((string) ($section['class_section_name'] ?? ($sid ? ('Section ' . $sid) : 'Class')));
            $url = trim((string) ($section['invite_link'] ?? ''));
            if ($url === '') {
                continue;
            }
            $key = $sid . '|' . $url;
            if (isset($seen[$key])) {
                continue;
            }
            $seen[$key] = true;

            $items[] = [
                'class_section_id' => $sid,
                'class_section_name' => $name,
                'invite_link' => $url,
                'qr_src' => $this->generateQrImage($url),
            ];
        }

        if (empty($items) && !empty($links)) {
            foreach ($links as $i => $url) {
                $url = trim((string) $url);
                if ($url === '') {
                    continue;
                }
                $key = '0|' . $url;
                if (isset($seen[$key])) {
                    continue;
                }
                $seen[$key] = true;
                $items[] = [
                    'class_section_id' => 0,
                    'class_section_name' => 'Class Link ' . ($i + 1),
                    'invite_link' => $url,
                    'qr_src' => $this->generateQrImage($url),
                ];
            }
        }

        return $items;
    }

    private function generateQrImage(string $inviteLink): string
    {
        if ($inviteLink === '') {
            return $this->qrFallback($inviteLink);
        }

        $dir = storage_path('app/qrcodes');
        if (!is_dir($dir)) {
            if (!@mkdir($dir, 0775, true) && !is_dir($dir)) {
                Log::error('QR: cannot create dir', ['dir' => $dir]);
                return $this->qrFallback($inviteLink);
            }
        }
        if (!is_writable($dir)) {
            Log::error('QR: dir not writable', ['dir' => $dir]);
            return $this->qrFallback($inviteLink);
        }

        $filename = 'wa_' . md5($inviteLink) . '.png';
        $path = $dir . DIRECTORY_SEPARATOR . $filename;

        if (!is_file($path)) {
            $v5BuilderClass = '\\Endroid\\QrCode\\Builder\\Builder';
            $v5WriterClass = '\\Endroid\\QrCode\\Writer\\PngWriter';
            $v5Encoding = '\\Endroid\\QrCode\\Encoding\\Encoding';

            $writerClass = '\\Endroid\\QrCode\\Writer\\PngWriter';
            $qrClass = '\\Endroid\\QrCode\\QrCode';

            $chlQRCode = '\\chillerlan\\QRCode\\QRCode';
            $chlQROptions = '\\chillerlan\\QRCode\\QROptions';
            $chlQRMatrix = '\\chillerlan\\QRCode\\Data\\QRMatrix';

            $lastErr = null;

            if (class_exists($v5BuilderClass) && class_exists($v5WriterClass)) {
                try {
                    $builder = $v5BuilderClass::create()
                        ->writer(new $v5WriterClass())
                        ->data($inviteLink);
                    if (class_exists($v5Encoding)) {
                        $builder->encoding(new $v5Encoding('UTF-8'));
                    }
                    $result = $builder->size(500)->margin(2)->build();
                    $result->saveToFile($path);
                } catch (\Throwable $e) {
                    $lastErr = 'Endroid v5: ' . $e->getMessage();
                }
            }

            if (!is_file($path) && class_exists($writerClass)) {
                try {
                    if (class_exists($qrClass) && method_exists($qrClass, 'create')) {
                        $qr = $qrClass::create($inviteLink);
                    } else {
                        $qr = class_exists($qrClass) ? new $qrClass($inviteLink) : null;
                    }
                    if ($qr) {
                        if (method_exists($qr, 'setSize')) {
                            $qr->setSize(500);
                        }
                        if (method_exists($qr, 'setMargin')) {
                            $qr->setMargin(2);
                        }
                        $writer = new $writerClass();
                        $result = $writer->write($qr);
                        if (method_exists($result, 'saveToFile')) {
                            $result->saveToFile($path);
                        } else {
                            $raw = method_exists($result, 'getString') ? $result->getString() : (string) $result;
                            file_put_contents($path, $raw);
                        }
                    }
                } catch (\Throwable $e) {
                    $lastErr = 'Endroid v3/v4: ' . $e->getMessage();
                }
            }

            if (!is_file($path) && class_exists($chlQRCode) && class_exists($chlQROptions)) {
                try {
                    $optsArr = [
                        'version' => 5,
                        'outputType' => constant($chlQRCode . '::OUTPUT_IMAGE_PNG'),
                        'scale' => 6,
                        'imageBase64' => false,
                        'quietzoneSize' => 2,
                    ];
                    if (class_exists($chlQRMatrix) && defined($chlQRMatrix . '::ECC_H')) {
                        $optsArr['eccLevel'] = constant($chlQRMatrix . '::ECC_H');
                    }

                    $opts = new $chlQROptions($optsArr);
                    $qrcode = new $chlQRCode($opts);
                    $png = $qrcode->render($inviteLink);
                    file_put_contents($path, $png);
                } catch (\Throwable $e) {
                    $lastErr = 'chillerlan: ' . $e->getMessage();
                }
            }

            if (!is_file($path) && $lastErr) {
                Log::error('QR generation failed', ['error' => $lastErr]);
            }
        }

        if (is_file($path)) {
            $data = @file_get_contents($path);
            if ($data !== false) {
                return 'data:image/png;base64,' . base64_encode($data);
            }
        }

        return $this->qrFallback($inviteLink);
    }

    private function qrFallback(string $inviteLink): string
    {
        $link = rawurlencode($inviteLink);
        return 'https://api.qrserver.com/v1/create-qr-code/?size=260x260&qzone=2&data=' . $link;
    }
}
