<?php

namespace App\Http\Controllers\Api\Email;

use App\Http\Controllers\Api\BaseApiController;
use App\Services\BroadcastEmail\BroadcastEmailComposerService;
use App\Services\BroadcastEmail\BroadcastEmailDispatchService;
use App\Services\BroadcastEmail\BroadcastEmailImageService;
use App\Services\BroadcastEmail\BroadcastEmailRecipientService;
use App\Services\BroadcastEmail\BroadcastEmailSenderOptionsService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class BroadcastEmailController extends BaseApiController
{
    private BroadcastEmailSenderOptionsService $senderOptions;
    private BroadcastEmailRecipientService $recipients;
    private BroadcastEmailComposerService $composer;
    private BroadcastEmailDispatchService $dispatch;
    private BroadcastEmailImageService $imageService;

    public function __construct(
        BroadcastEmailSenderOptionsService $senderOptions,
        BroadcastEmailRecipientService $recipients,
        BroadcastEmailComposerService $composer,
        BroadcastEmailDispatchService $dispatch,
        BroadcastEmailImageService $imageService
    ) {
        parent::__construct();
        $this->senderOptions = $senderOptions;
        $this->recipients = $recipients;
        $this->composer = $composer;
        $this->dispatch = $dispatch;
        $this->imageService = $imageService;
    }

    public function options(): JsonResponse
    {
        return response()->json([
            'ok' => true,
            'parents' => $this->recipients->parentsWithEmails(),
            'fromOptions' => $this->senderOptions->listOptions(),
        ]);
    }

    public function send(Request $request): JsonResponse
    {
        $mode = (string) ($request->input('mode') ?? 'standard');
        $subject = trim((string) ($request->input('subject') ?? ''));
        $fromKey = trim((string) ($request->input('from_key') ?? 'general'));
        $body = (string) ($request->input('body_html') ?? '');
        $wrapLayout = (bool) $request->boolean('wrap_layout');
        $preheader = (string) ($request->input('preheader') ?? '');
        $ctaText = (string) ($request->input('cta_text') ?? '');
        $ctaUrl = (string) ($request->input('cta_url') ?? '');
        $testEmail = trim((string) ($request->input('test_email') ?? ''));
        $isTestOnly = (bool) $request->boolean('send_test_only');

        $body = $this->composer->sanitizeHtml($body);

        if ($subject === '' || $body === '') {
            return response()->json([
                'ok' => false,
                'message' => 'Subject and Body are required.',
            ], 422);
        }

        $personalize = $mode === 'personalized';

        if ($isTestOnly) {
            if ($testEmail === '') {
                return response()->json([
                    'ok' => false,
                    'message' => 'Provide a test email address.',
                ], 422);
            }

            $result = $this->dispatch->sendTest([
                'wrap_layout' => $wrapLayout,
                'subject' => $subject,
                'body_html' => $body,
                'recipient_name' => 'Parent',
                'preheader' => $preheader,
                'cta_text' => $ctaText,
                'cta_url' => $ctaUrl,
                'personalize' => $personalize,
                'test_email' => $testEmail,
                'from_key' => $fromKey,
            ]);

            return response()->json($result, $result['ok'] ? 200 : 500);
        }

        $rawIds = $request->input('parent_ids', []);
        $ids = $this->normalizeIds($rawIds);

        if (empty($ids)) {
            return response()->json([
                'ok' => false,
                'message' => 'Please select at least one parent.',
            ], 422);
        }

        $recipients = $this->recipients->recipientsByIds($ids);

        if (empty($recipients)) {
            return response()->json([
                'ok' => false,
                'message' => 'No valid parent emails found.',
            ], 422);
        }

        $stats = $this->dispatch->sendBroadcast([
            'wrap_layout' => $wrapLayout,
            'subject' => $subject,
            'body_html' => $body,
            'preheader' => $preheader,
            'cta_text' => $ctaText,
            'cta_url' => $ctaUrl,
            'personalize' => $personalize,
            'from_key' => $fromKey,
            'mode' => $mode,
        ], $recipients);

        $message = sprintf(
            'Broadcast finished. Mode: %s. Sent: %d/%d. Failures: %d.',
            $stats['mode'],
            $stats['sent'],
            $stats['attempted'],
            $stats['failed']
        );

        return response()->json([
            'ok' => $stats['failed'] === 0,
            'stats' => $stats,
            'message' => $message,
        ]);
    }

    public function uploadImage(Request $request): JsonResponse
    {
        $file = $request->file('image');
        if (!$file || !$file->isValid()) {
            return response()->json([
                'success' => false,
                'error' => 'No image uploaded',
            ], 400);
        }

        $result = $this->imageService->store($file);
        if (!$result['ok']) {
            return response()->json([
                'success' => false,
                'error' => $result['error'] ?? 'Upload failed',
            ], $result['status'] ?? 400);
        }

        $newHash = function_exists('csrf_hash') ? csrf_hash() : csrf_token();

        return response()->json([
            'success' => true,
            'url' => $result['url'],
            'csrf_hash' => $newHash,
        ])->header('X-CSRF-HASH', (string) $newHash);
    }

    private function normalizeIds($rawIds): array
    {
        $ids = [];
        $raw = is_array($rawIds) ? $rawIds : [$rawIds];

        foreach ($raw as $value) {
            if (is_string($value) && strpos($value, ',') !== false) {
                foreach (explode(',', $value) as $piece) {
                    $ids[] = (int) $piece;
                }
                continue;
            }
            $ids[] = (int) $value;
        }

        return array_values(array_unique(array_filter($ids)));
    }
}
