<?php

declare(strict_types=1);

namespace Lab;

final class Mailer
{
    public static function sendNewOrder(array $order, array $config): bool
    {
        $to = (string) ($config['mail']['to'] ?? $config['business']['email'] ?? '');
        $code = (string) ($order['code'] ?? '');
        $name = (string) ($order['customer_name'] ?? '');
        $phone = (string) ($order['customer_phone'] ?? '');
        $email = (string) ($order['customer_email'] ?? '—');
        $channel = Helpers::channelLabel((string) ($order['channel'] ?? ''));
        $store = (string) ($order['store_id'] ?? '—');
        $total = Helpers::euro((int) ($order['total_cents'] ?? 0));
        $notes = trim((string) ($order['notes'] ?? '')) ?: '—';
        $items = json_decode((string) ($order['items_json'] ?? '[]'), true);
        $lines = [];
        if (is_array($items)) {
            foreach ($items as $item) {
                foreach (($item['lines'] ?? []) as $line) {
                    $lines[] = sprintf(
                        '  • %s — %s ×%d',
                        $item['original_name'] ?? '',
                        $line['name'] ?? $line['sku'] ?? '',
                        (int) ($line['qty'] ?? 1)
                    );
                }
            }
        }
        $itemList = implode("\n", $lines) ?: '  —';
        $subject = 'Νέα παραγγελία Lab ' . $code;
        $body = <<<TEXT
Νέα παραγγελία Panorama Lab

Κωδικός: {$code}
Κανάλι: {$channel}
Πελάτης: {$name}
Τηλέφωνο: {$phone}
Email: {$email}
Κατάστημα: {$store}
Σύνολο: {$total}

Εκτυπώσεις:
{$itemList}

Σημειώσεις:
{$notes}
TEXT;

        $ok = self::send($to, $subject, $body, $config, filter_var($email, FILTER_VALIDATE_EMAIL) ? $email : null);
        if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $copy = <<<TEXT
Αγαπητέ/ή {$name},

Η παραγγελία σας καταχωρήθηκε.

Κωδικός: {$code}
Σύνολο: {$total}

Θα σας ειδοποιήσουμε στο {$phone} όταν είναι έτοιμη.

Πανόραμα
https://magicphotobooth.gr
info@magicphotobooth.gr
2421200132
TEXT;
            self::send($email, 'Η παραγγελία ' . $code . ' καταχωρήθηκε', $copy, $config, null);
        }

        return $ok;
    }

    public static function send(string $to, string $subject, string $body, array $config, ?string $replyTo = null): bool
    {
        $driver = (string) ($config['mail']['driver'] ?? 'log');
        if ($driver !== 'smtp' || trim((string) ($config['mail']['smtp']['password'] ?? '')) === '') {
            return self::log($to, $subject, $body, $config);
        }

        return self::smtp($to, $subject, $body, $config, $replyTo);
    }

    private static function log(string $to, string $subject, string $body, array $config): bool
    {
        $dir = dirname((string) ($config['db_path'] ?? dirname(__DIR__) . '/data/lab.sqlite'));
        if (! is_dir($dir)) {
            mkdir($dir, 0755, true);
        }
        $entry = '[' . date('c') . "] To: {$to}\nSubject: {$subject}\n\n{$body}\n\n----\n";
        file_put_contents($dir . '/mail.log', $entry, FILE_APPEND);

        return true;
    }

    private static function smtp(string $to, string $subject, string $body, array $config, ?string $replyTo): bool
    {
        $smtp = $config['mail']['smtp'] ?? [];
        $host = (string) ($smtp['host'] ?? '');
        $port = (int) ($smtp['port'] ?? 465);
        $encryption = (string) ($smtp['encryption'] ?? 'ssl');
        $username = (string) ($smtp['username'] ?? '');
        $password = (string) ($smtp['password'] ?? '');
        $fromEmail = (string) ($config['mail']['from_email'] ?? $username);
        $fromName = (string) ($config['mail']['from_name'] ?? 'Panorama Lab');
        $reply = $replyTo ?: (string) ($config['mail']['reply_to'] ?? $fromEmail);

        $remote = ($encryption === 'ssl' ? 'ssl://' : '') . $host . ':' . $port;
        $ctx = stream_context_create(['ssl' => [
            'verify_peer' => false,
            'verify_peer_name' => false,
            'allow_self_signed' => true,
        ]]);
        $socket = @stream_socket_client($remote, $errno, $errstr, 20, STREAM_CLIENT_CONNECT, $ctx);
        if (! is_resource($socket)) {
            return self::log($to, $subject, $body . "\n\nSMTP FAIL: {$errstr}", $config);
        }
        stream_set_timeout($socket, 20);
        $read = static function () use ($socket): string {
            $data = '';
            while (! feof($socket)) {
                $line = fgets($socket, 515);
                if ($line === false) {
                    break;
                }
                $data .= $line;
                if (isset($line[3]) && $line[3] === ' ') {
                    break;
                }
            }

            return $data;
        };
        $write = static function (string $command) use ($socket): void {
            fwrite($socket, $command . "\r\n");
        };
        $ok = static function (string $response, array $codes): bool {
            return in_array((int) substr($response, 0, 3), $codes, true);
        };

        try {
            if (! $ok($read(), [220])) {
                return false;
            }
            $write('EHLO magicphotobooth.gr');
            if (! $ok($read(), [250])) {
                $write('HELO magicphotobooth.gr');
                if (! $ok($read(), [250])) {
                    return false;
                }
            }
            if ($encryption === 'tls') {
                $write('STARTTLS');
                if (! $ok($read(), [220])) {
                    return false;
                }
                if (! stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
                    return false;
                }
                $write('EHLO magicphotobooth.gr');
                $read();
            }
            if ($username !== '') {
                $write('AUTH LOGIN');
                if (! $ok($read(), [334])) {
                    return false;
                }
                $write(base64_encode($username));
                if (! $ok($read(), [334])) {
                    return false;
                }
                $write(base64_encode($password));
                if (! $ok($read(), [235])) {
                    return false;
                }
            }
            $write('MAIL FROM:<' . $fromEmail . '>');
            if (! $ok($read(), [250])) {
                return false;
            }
            $write('RCPT TO:<' . $to . '>');
            if (! $ok($read(), [250, 251])) {
                return false;
            }
            $write('DATA');
            if (! $ok($read(), [354])) {
                return false;
            }
            $headers = [
                'Date: ' . date('r'),
                'From: =?UTF-8?B?' . base64_encode($fromName) . '?= <' . $fromEmail . '>',
                'To: <' . $to . '>',
                'Subject: =?UTF-8?B?' . base64_encode($subject) . '?=',
                'MIME-Version: 1.0',
                'Content-Type: text/plain; charset=UTF-8',
                'Content-Transfer-Encoding: 8bit',
                'Reply-To: ' . $reply,
            ];
            $safeBody = preg_replace('/^\./m', '..', str_replace(["\r\n", "\r"], "\n", $body)) ?? $body;
            $write(implode("\r\n", array_merge($headers, ['', $safeBody, '.'])));
            if (! $ok($read(), [250])) {
                return false;
            }
            $write('QUIT');
            $read();

            return true;
        } finally {
            fclose($socket);
        }
    }
}
