<?php

namespace App\Domain\WhatsApp\Services;

use App\Domain\WhatsApp\Enums\MessageStatus;
use App\Domain\WhatsApp\Enums\MessageType;
use App\Domain\WhatsApp\Models\WhatsAppMessage;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class WhatsAppService
{
    private string $apiVersion;
    private string $phoneNumberId;
    private string $accessToken;
    private string $baseUrl;

    public function __construct()
    {
        $this->apiVersion = config('services.whatsapp.api_version', 'v25.0');
        $this->phoneNumberId = config('services.whatsapp.phone_number_id', '');
        $this->accessToken = config('services.whatsapp.access_token', '');
        $this->baseUrl = "https://graph.facebook.com/{$this->apiVersion}/{$this->phoneNumberId}";
    }

    public function sendTemplate(
        string $to,
        string $templateName,
        string $languageCode = 'en_US',
        array $components = [],
        ?int $academyId = null,
        ?int $senderId = null,
    ): WhatsAppMessage {
        $to = $this->formatPhone($to);

        $payload = [
            'messaging_product' => 'whatsapp',
            'to' => $to,
            'type' => 'template',
            'template' => [
                'name' => $templateName,
                'language' => ['code' => $languageCode],
            ],
        ];

        if (!empty($components)) {
            $payload['template']['components'] = $components;
        }

        $response = $this->sendRequest($payload);

        return $this->logMessage(
            academyId: $academyId,
            to: $to,
            type: MessageType::Template,
            content: $templateName,
            payload: $payload,
            response: $response,
            senderId: $senderId,
        );
    }

    public function sendText(
        string $to,
        string $body,
        ?int $academyId = null,
        ?int $senderId = null,
        bool $previewUrl = false,
    ): WhatsAppMessage {
        $to = $this->formatPhone($to);

        $payload = [
            'messaging_product' => 'whatsapp',
            'to' => $to,
            'type' => 'text',
            'text' => [
                'preview_url' => $previewUrl,
                'body' => $body,
            ],
        ];

        $response = $this->sendRequest($payload);

        return $this->logMessage(
            academyId: $academyId,
            to: $to,
            type: MessageType::Text,
            content: $body,
            payload: $payload,
            response: $response,
            senderId: $senderId,
        );
    }

    public function sendImage(
        string $to,
        string $imageUrl,
        ?string $caption = null,
        ?int $academyId = null,
        ?int $senderId = null,
    ): WhatsAppMessage {
        $to = $this->formatPhone($to);

        $payload = [
            'messaging_product' => 'whatsapp',
            'to' => $to,
            'type' => 'image',
            'image' => [
                'link' => $imageUrl,
            ],
        ];

        if ($caption) {
            $payload['image']['caption'] = $caption;
        }

        $response = $this->sendRequest($payload);

        return $this->logMessage(
            academyId: $academyId,
            to: $to,
            type: MessageType::Image,
            content: $caption ?? $imageUrl,
            payload: $payload,
            response: $response,
            senderId: $senderId,
        );
    }

    public function sendDocument(
        string $to,
        string $documentUrl,
        ?string $filename = null,
        ?string $caption = null,
        ?int $academyId = null,
        ?int $senderId = null,
    ): WhatsAppMessage {
        $to = $this->formatPhone($to);

        $payload = [
            'messaging_product' => 'whatsapp',
            'to' => $to,
            'type' => 'document',
            'document' => [
                'link' => $documentUrl,
            ],
        ];

        if ($filename) {
            $payload['document']['filename'] = $filename;
        }
        if ($caption) {
            $payload['document']['caption'] = $caption;
        }

        $response = $this->sendRequest($payload);

        return $this->logMessage(
            academyId: $academyId,
            to: $to,
            type: MessageType::Document,
            content: $caption ?? $filename ?? $documentUrl,
            payload: $payload,
            response: $response,
            senderId: $senderId,
        );
    }

    public function sendBulkTemplate(
        array $recipients,
        string $templateName,
        string $languageCode = 'en_US',
        array $components = [],
        ?int $academyId = null,
        ?int $senderId = null,
    ): array {
        $results = ['sent' => 0, 'failed' => 0, 'messages' => []];

        foreach ($recipients as $phone) {
            try {
                $msg = $this->sendTemplate($phone, $templateName, $languageCode, $components, $academyId, $senderId);
                if ($msg->status === MessageStatus::Failed) {
                    $results['failed']++;
                } else {
                    $results['sent']++;
                }
                $results['messages'][] = $msg;
            } catch (\Throwable $e) {
                $results['failed']++;
                Log::warning("WhatsApp bulk send failed for {$phone}: {$e->getMessage()}");
            }
        }

        return $results;
    }

    public function sendBulkText(
        array $recipients,
        string $body,
        ?int $academyId = null,
        ?int $senderId = null,
    ): array {
        $results = ['sent' => 0, 'failed' => 0, 'messages' => []];

        foreach ($recipients as $phone) {
            try {
                $msg = $this->sendText($phone, $body, $academyId, $senderId);
                if ($msg->status === MessageStatus::Failed) {
                    $results['failed']++;
                } else {
                    $results['sent']++;
                }
                $results['messages'][] = $msg;
            } catch (\Throwable $e) {
                $results['failed']++;
                Log::warning("WhatsApp bulk text failed for {$phone}: {$e->getMessage()}");
            }
        }

        return $results;
    }

    public function isConfigured(): bool
    {
        return !empty($this->phoneNumberId) && !empty($this->accessToken);
    }

    private function sendRequest(array $payload): array
    {
        if (!$this->isConfigured()) {
            return ['error' => ['message' => 'WhatsApp API not configured']];
        }

        $response = Http::withToken($this->accessToken)
            ->timeout(30)
            ->post("{$this->baseUrl}/messages", $payload);

        $data = $response->json();

        if (!$response->successful()) {
            Log::error('WhatsApp API error', [
                'status' => $response->status(),
                'body' => $data,
                'payload_to' => $payload['to'] ?? null,
            ]);
        }

        return $data ?? [];
    }

    private function logMessage(
        ?int $academyId,
        string $to,
        MessageType $type,
        string $content,
        array $payload,
        array $response,
        ?int $senderId,
    ): WhatsAppMessage {
        $waMessageId = $response['messages'][0]['id'] ?? null;
        $status = $waMessageId ? MessageStatus::Sent : MessageStatus::Failed;
        $errorMessage = null;

        if (!$waMessageId) {
            $errorMessage = $response['error']['message']
                ?? $response['error']['error_data']['details'] ?? 'Unknown error';
        }

        return WhatsAppMessage::create([
            'academy_id' => $academyId ?? (int) app('current_academy')?->id,
            'wa_message_id' => $waMessageId,
            'phone_number' => $to,
            'type' => $type->value,
            'content' => mb_substr($content, 0, 2000),
            'status' => $status->value,
            'error_message' => $errorMessage,
            'payload' => $payload,
            'response' => $response,
            'sent_by' => $senderId ?? auth()->id(),
            'sent_at' => $waMessageId ? now() : null,
        ]);
    }

    private function formatPhone(string $phone): string
    {
        $phone = preg_replace('/[\s\-\(\)\+]/', '', $phone);

        if (str_starts_with($phone, '0')) {
            $phone = '20' . substr($phone, 1);
        } elseif (strlen($phone) === 10) {
            $phone = '20' . $phone;
        }

        return $phone;
    }
}
