<?php

namespace App\Http\Controllers\API;

use App\Http\Controllers\Controller;
use App\Models\Group;
use App\Models\Number;
use App\Models\SmsMessage;
use App\Services\FcmService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class SmsMessageController extends Controller
{
    /**
     * Get paginated SMS messages queue and status counts.
     */
    public function index(Request $request): JsonResponse
    {
        $userId = $request->user()->id;
        $status = $request->string('status')->toString();
        $keyword = $request->string('phone')->toString();
        $statuses = [
            SmsMessage::STATUS_PENDING,
            SmsMessage::STATUS_PROCESSING,
            SmsMessage::STATUS_SENT,
            SmsMessage::STATUS_FAILED,
        ];

        $query = SmsMessage::query()
            ->where('user_id', $userId)
            ->when(in_array($status, $statuses, true), fn ($q) => $q->where('status', $status))
            ->when($keyword, fn ($q) => $q->where('recipient', 'LIKE', "%{$keyword}%"))
            ->latest();

        $messages = $query->paginate($request->integer('perPage', 15));

        $counts = SmsMessage::query()
            ->where('user_id', $userId)
            ->selectRaw('status, count(*) as total')
            ->groupBy('status')
            ->pluck('total', 'status');

        return appResponse([
            'status' => 2000,
            'data' => $messages,
            'counts' => [
                'all' => (int) $counts->sum(),
                'pending' => (int) ($counts->get('pending') ?? 0),
                'processing' => (int) ($counts->get('processing') ?? 0),
                'sent' => (int) ($counts->get('sent') ?? 0),
                'failed' => (int) ($counts->get('failed') ?? 0),
            ],
            'filter_status' => $status,
        ]);
    }

    /**
     * Store new SMS message(s) in the pending queue (Single or Group) and trigger FCM Push Notification.
     */
    public function store(Request $request): JsonResponse
    {
        $userId = $request->user()->id;
        $sendType = $request->input('send_type', 'single');
        $message = trim((string) $request->input('message'));

        $targetDeviceId = $request->input('device_id');
        if ($targetDeviceId) {
            $deviceModel = \App\Models\UserDevice::where('user_id', $userId)
                ->where(function ($q) use ($targetDeviceId) {
                    $q->where('id', $targetDeviceId)->orWhere('device_id', $targetDeviceId);
                })->first();
            $targetDeviceId = $deviceModel ? $deviceModel->id : (is_numeric($targetDeviceId) ? (int) $targetDeviceId : null);
        }

        if (empty($message)) {
            return appResponse([
                'status' => 4022,
                'message' => 'The message content is required.',
            ], 422);
        }

        if (mb_strlen($message) > 1000) {
            return appResponse([
                'status' => 4022,
                'message' => 'The message cannot exceed 1000 characters.',
            ], 422);
        }

        // 1. Handle Group SMS dispatch to Queue
        if ($sendType === 'group' || ($request->filled('group_id') && empty($request->input('recipient')))) {
            $groupId = (int) $request->input('group_id');
            $group = Group::where('id', $groupId)
                ->where(function ($q) use ($userId) {
                    $q->where('user_id', $userId)->orWhere('user_id', 0);
                })
                ->first();

            if (!$group) {
                return appResponse([
                    'status' => 4004,
                    'message' => 'Selected group was not found.',
                ], 404);
            }

            $numbers = Number::where('group_id', $group->id)
                ->where(function ($q) use ($userId) {
                    $q->where('user_id', $userId)->orWhere('user_id', 0);
                })
                ->get();

            if ($numbers->isEmpty()) {
                return appResponse([
                    'status' => 4022,
                    'message' => "Group '{$group->name}' does not contain any contact numbers.",
                ], 422);
            }

            $createdCount = 0;
            $insertRows = [];
            $now = now();

            foreach ($numbers as $num) {
                $rawPhone = $num->number ?: $num->phone;
                $cleanPhone = preg_replace('/[^\d+]/', '', trim((string) $rawPhone));

                if (empty($cleanPhone) || strlen($cleanPhone) < 6) {
                    continue;
                }

                $insertRows[] = [
                    'user_id' => $userId,
                    'device_id' => $targetDeviceId,
                    'recipient' => $cleanPhone,
                    'message' => $message,
                    'status' => SmsMessage::STATUS_PENDING,
                    'attempts' => 0,
                    'created_at' => $now,
                    'updated_at' => $now,
                ];
                $createdCount++;
            }

            if (count($insertRows) === 0) {
                return appResponse([
                    'status' => 4022,
                    'message' => 'No valid phone numbers could be processed in this group.',
                ], 422);
            }

            foreach (array_chunk($insertRows, 500) as $batch) {
                SmsMessage::insert($batch);
            }

            // Send Group FCM Push Notification to user's mobile device
            FcmService::sendGroupMessageNotification(
                $userId,
                $group->id,
                $group->name,
                $createdCount,
                $message,
                $targetDeviceId
            );

            return appResponse([
                'status' => 2000,
                'message' => "Successfully added {$createdCount} SMS message(s) to the queue for group '{$group->name}'.",
                'queued_count' => $createdCount,
                'group' => [
                    'id' => $group->id,
                    'name' => $group->name,
                    'total_numbers' => $createdCount,
                ],
            ]);
        }

        // 2. Handle Single Number or Comma-separated Numbers
        $rawRecipient = (string) $request->input('recipient');
        $recipientItems = preg_split('/[\r\n,]+/', $rawRecipient);
        $validRecipients = [];

        foreach ($recipientItems as $item) {
            $cleaned = preg_replace('/[^\d+]/', '', trim($item));
            if (!empty($cleaned) && preg_match('/^\+?[0-9]{6,15}$/', $cleaned)) {
                $validRecipients[] = $cleaned;
            }
        }

        if (empty($validRecipients)) {
            return appResponse([
                'status' => 4022,
                'message' => 'Please provide at least one valid recipient phone number (6-15 digits).',
            ], 422);
        }

        $createdCount = 0;
        $lastCreated = null;
        $now = now();
        $isLargeMessage = count($validRecipients) > 1 || mb_strlen($message) > 300;

        if ($isLargeMessage) {
            $insertRows = [];
            foreach ($validRecipients as $cleanPhone) {
                $insertRows[] = [
                    'user_id' => $userId,
                    'device_id' => $targetDeviceId,
                    'recipient' => $cleanPhone,
                    'message' => $message,
                    'status' => SmsMessage::STATUS_PENDING,
                    'attempts' => 0,
                    'created_at' => $now,
                    'updated_at' => $now,
                ];
                $createdCount++;
            }

            foreach (array_chunk($insertRows, 500) as $batch) {
                SmsMessage::insert($batch);
            }

            // Send Large Message Push Notification
            FcmService::sendLargeMessageNotification(
                $userId,
                $createdCount,
                'Bulk Direct SMS',
                $message,
                $targetDeviceId
            );
        } else {
            // Single small message: Push instantly for immediate phone delivery
            $cleanPhone = $validRecipients[0];
            $smsMessage = SmsMessage::create([
                'user_id' => $userId,
                'device_id' => $targetDeviceId,
                'recipient' => $cleanPhone,
                'message' => $message,
                'status' => SmsMessage::STATUS_PENDING,
            ]);

            $lastCreated = $smsMessage;
            $createdCount = 1;

            FcmService::sendNewSmsNotification(
                $userId,
                $smsMessage->recipient,
                $smsMessage->message,
                $smsMessage->id,
                $targetDeviceId
            );
        }

        $successMsg = $createdCount === 1
            ? 'SMS added to the pending queue successfully.'
            : "Successfully added {$createdCount} SMS messages to the queue.";

        return appResponse([
            'status' => 2000,
            'message' => $successMsg,
            'queued_count' => $createdCount,
            'data' => $lastCreated,
        ]);
    }

    /**
     * Retry failed or processing SMS message (return to pending queue).
     */
    public function retry(Request $request, $id): JsonResponse
    {
        $userId = $request->user()->id;
        $smsMessage = SmsMessage::where('id', $id)->where('user_id', $userId)->first();

        if (!$smsMessage) {
            return appResponse([
                'status' => 4004,
                'message' => 'SMS message not found.',
            ], 404);
        }

        if (!in_array($smsMessage->status, [SmsMessage::STATUS_FAILED, SmsMessage::STATUS_PROCESSING], true)) {
            return appResponse([
                'status' => 4000,
                'message' => 'Only failed or processing messages can be returned to the queue.',
            ], 422);
        }

        $smsMessage->update([
            'status' => SmsMessage::STATUS_PENDING,
            'claimed_at' => null,
            'sent_at' => null,
            'failed_at' => null,
            'last_error' => null,
        ]);

        // Re-dispatch FCM notification to mobile app
        FcmService::sendNewSmsNotification(
            $userId,
            $smsMessage->recipient,
            $smsMessage->message,
            $smsMessage->id
        );

        return appResponse([
            'status' => 2000,
            'message' => 'SMS returned to the pending queue successfully.',
            'data' => $smsMessage->fresh(),
        ]);
    }
}
