<?php

namespace App\Http\Controllers\Tenant;

use App\Http\Controllers\Controller;
use App\Models\Customer;
use App\Models\NotificationCampaign;
use App\Services\CustomerNotificationService;
use App\Services\PlatformSettings;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\View\View;

class CustomerNotificationController extends Controller
{
    public function index(Request $request, PlatformSettings $settings): View
    {
        $tenant = $request->user()->tenant;

        return view('tenant.customer-notifications.index', [
            'customers' => Customer::withoutGlobalScopes()
                ->where('tenant_id', $tenant->id)
                ->visibleTo($request->user())
                ->orderBy('first_name')
                ->orderBy('last_name')
                ->get(),
            'campaigns' => NotificationCampaign::with(['createdBy', 'recipients'])
                ->where('tenant_id', $tenant->id)
                ->whereIn('recipient_type', ['customer', 'external', 'bulk_sms'])
                ->latest()
                ->paginate(10),
            'smsConfigured' => $settings->smsConfigured($tenant),
            'whatsappConfigured' => $settings->whatsappConfigured($tenant),
        ]);
    }

    public function store(Request $request, CustomerNotificationService $notifications): RedirectResponse
    {
        $tenantId = $request->user()->tenant_id;

        $validator = Validator::make($request->all(), [
            'subject' => ['required', 'string', 'max:255'],
            'message' => ['required', 'string', 'max:5000'],
            'channels' => ['required', 'array', 'min:1'],
            'channels.*' => ['required', 'in:email,sms,portal,whatsapp'],
            'audience_type' => ['required', 'in:all,individual,status,kyc,numbers'],
            'customer_ids' => ['nullable', 'array'],
            'customer_ids.*' => ['integer'],
            'customer_status' => ['nullable', 'in:active,inactive,suspended'],
            'kyc_status' => ['nullable', 'in:pending,verified,rejected'],
            'custom_recipients' => ['nullable', 'string', 'max:20000'],
            'phone_numbers' => ['nullable', 'string', 'max:20000'],
        ]);

        $validator->after(function ($validator) use ($request, $tenantId): void {
            if ($request->audience_type === 'individual') {
                $ids = collect($request->input('customer_ids', []))
                    ->filter()
                    ->map(fn ($id) => (int) $id)
                    ->unique()
                    ->values();

                if ($ids->isEmpty()) {
                    $validator->errors()->add('customer_ids', 'Select at least one customer.');
                    return;
                }

                $validCount = Customer::withoutGlobalScopes()
                    ->where('tenant_id', $tenantId)
                    ->visibleTo($request->user())
                    ->whereIn('id', $ids)
                    ->count();

                if ($validCount !== $ids->count()) {
                    $validator->errors()->add('customer_ids', 'One or more selected customers do not belong to your company.');
                }
            }

            if ($request->audience_type === 'status' && blank($request->customer_status)) {
                $validator->errors()->add('customer_status', 'Select a customer group.');
            }

            if ($request->audience_type === 'kyc' && blank($request->kyc_status)) {
                $validator->errors()->add('kyc_status', 'Select a KYC group.');
            }

            if ($request->audience_type === 'numbers') {
                $channels = collect($request->input('channels', []));

                if ($channels->contains('portal')) {
                    $validator->errors()->add('channels', 'Portal messages can only be sent to registered members.');
                }

                $summary = $this->customRecipientSummary(
                    (string) ($request->input('custom_recipients') ?: $request->input('phone_numbers'))
                );

                if ($summary['total'] === 0) {
                    $validator->errors()->add('custom_recipients', 'Enter at least one phone number or email address.');
                }

                if ($channels->intersect(['sms', 'whatsapp'])->isNotEmpty() && $summary['phones'] === 0) {
                    $validator->errors()->add('custom_recipients', 'Enter at least one phone number for SMS or WhatsApp.');
                }

                if ($channels->contains('email') && $summary['emails'] === 0) {
                    $validator->errors()->add('custom_recipients', 'Enter at least one email address for email messages.');
                }
            }
        });

        $campaign = $notifications->send($validator->validate(), $request->user());
        $recipientLabel = $campaign->recipient_type === 'external' || $campaign->recipient_type === 'bulk_sms'
            ? 'contact'
            : 'member';

        return redirect()
            ->route('tenant.customer-notifications.index')
            ->with('status', 'Notification sent to '.$campaign->total_recipients.' '.$recipientLabel.($campaign->total_recipients === 1 ? '' : 's').'.');
    }

    public function resendFailed(Request $request, NotificationCampaign $campaign, CustomerNotificationService $notifications): RedirectResponse
    {
        $tenant = $request->user()->tenant;

        abort_unless($tenant && (int) $campaign->tenant_id === (int) $tenant->id, 404);
        abort_unless(in_array($campaign->recipient_type, ['customer', 'external', 'bulk_sms'], true), 404);

        $result = $notifications->resendFailed($campaign, $request->user());

        if ($result['attempted'] === 0) {
            return redirect()
                ->route('tenant.customer-notifications.index')
                ->with('status', 'There are no failed email, SMS, or WhatsApp deliveries to resend for that campaign.');
        }

        $message = 'Retried '.$result['attempted'].' failed deliver'.($result['attempted'] === 1 ? 'y' : 'ies').'. '
            .$result['sent'].' succeeded, '.$result['failed'].' still failed.';

        return redirect()
            ->route('tenant.customer-notifications.index')
            ->with($result['failed'] > 0 ? 'warning' : 'status', $message);
    }

    private function customRecipientSummary(string $raw): array
    {
        return collect(preg_split('/[\r\n,;]+/', $raw) ?: [])
            ->map(fn (string $value): string => trim($value))
            ->filter()
            ->reduce(function (array $summary, string $value): array {
                if (filter_var($value, FILTER_VALIDATE_EMAIL)) {
                    $summary['emails']++;
                    $summary['total']++;

                    return $summary;
                }

                $phone = preg_replace('/(?!^\+)[^\d]/', '', $value) ?: '';

                if ($phone !== '') {
                    $summary['phones']++;
                    $summary['total']++;
                }

                return $summary;
            }, ['phones' => 0, 'emails' => 0, 'total' => 0]);
    }
}
