<?php
// modules/Chatwoot/app/Services/ChatwootSyncService.php

namespace Modules\Chatwoot\Services;

use Modules\Chatwoot\Services\ChatwootApiService;
use Modules\Chatwoot\Services\ChatwootLogService;
use Modules\Contacts\Models\Contact;
use Modules\Contacts\Models\Phone;
use Modules\Contacts\Models\Company;
use Carbon\Carbon;
use Modules\Contacts\Enums\PhoneType; 

class ChatwootSyncService
{
    protected $apiService;
    protected $logService;

    public function __construct(ChatwootApiService $apiService, ChatwootLogService $logService)
    {
        $this->apiService = $apiService;
        $this->logService = $logService;
    }

    /**
     * Sync contact from Chatwoot to CRM
     */
    public function syncContactToCRM(array $chatwootContact): ?Contact
    {
        try {
            $email = $chatwootContact['email'] ?? null;
            $phone = $chatwootContact['phone_number'] ?? null;

            if (!$email && !$phone) {
                $this->logService->warning('Contact has no email or phone', ['contact' => $chatwootContact]);
                return null;
            }

            // Buscar contato existente
            $contact = $this->findExistingContact($chatwootContact);

            $contactData = $this->mapChatwootContactToCRM($chatwootContact);

            if ($contact) {
                // Atualizar contato existente
                $contact->fill($contactData);
                $contact->save();
                
                $this->logService->info('Contact updated from Chatwoot', [
                    'contact_id' => $contact->id,
                    'chatwoot_id' => $chatwootContact['id']
                ]);
                $action = 'updated';
            } else {
                // Criar novo contato
                $contact = Contact::create($contactData);
                
                $this->logService->info('Contact created from Chatwoot', [
                    'contact_id' => $contact->id,
                    'chatwoot_id' => $chatwootContact['id']
                ]);
                $action = 'created';
            }

            // Sincronizar telefones
            $this->syncContactPhones($contact, $chatwootContact);

            // Salvar ID do Chatwoot como campo personalizado
            $this->setCustomField($contact, 'cf_chatwootid_contato', $chatwootContact['id']);

            $this->logService->info("Contact {$action} successfully", [
                'contact_id' => $contact->id,
                'chatwoot_id' => $chatwootContact['id'],
                'email' => $email,
                'phone' => $phone
            ]);

            return $contact;

        } catch (\Exception $e) {
            $this->logService->error('Failed to sync contact to CRM', [
                'chatwoot_contact' => $chatwootContact,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            return null;
        }
    }

    /**
     * Find existing contact by multiple criteria
     */
    protected function findExistingContact(array $chatwootContact): ?Contact
    {
        $email = $chatwootContact['email'] ?? null;
        $phone = $chatwootContact['phone_number'] ?? null;
        $chatwootId = $chatwootContact['id'] ?? null;

        // 1. Buscar por email
        if ($email) {
            $contact = Contact::where('email', $email)->first();
            if ($contact) {
                return $contact;
            }
        }

        // 2. Buscar por ID do Chatwoot no campo personalizado
        if ($chatwootId) {
            $contact = $this->findByCustomField('cf_chatwootid_contato', $chatwootId);
            if ($contact) {
                return $contact;
            }
        }

        // 3. Buscar por telefone
        if ($phone) {
            $cleanPhone = $this->cleanPhoneNumber($phone);
            $contact = Contact::whereHas('phones', function ($query) use ($cleanPhone, $phone) {
                $query->where('number', 'like', '%' . $cleanPhone . '%')
                      ->orWhere('number', 'like', '%' . $phone . '%');
            })->first();
            if ($contact) {
                return $contact;
            }
        }

        return null;
    }

    /**
     * Find contact by custom field
     */
    protected function findByCustomField(string $fieldName, $value): ?Contact
    {
        try {
            // Tentar diferentes abordagens para encontrar por campo personalizado
            
            // Abordagem 1: Campo direto na tabela
            $contact = Contact::where($fieldName, $value)->first();
            if ($contact) {
                return $contact;
            }

            // Abordagem 2: Através de relacionamento customFields (se existir)
            if (method_exists(Contact::class, 'customFields')) {
                $contact = Contact::whereHas('customFields', function ($query) use ($fieldName, $value) {
                    $query->where('field_id', $fieldName)
                          ->where('field_value', $value);
                })->first();
                if ($contact) {
                    return $contact;
                }
            }

            // Abordagem 3: Buscar em JSON field (se existir)
            $contact = Contact::whereJsonContains('custom_fields->' . $fieldName, $value)->first();
            if ($contact) {
                return $contact;
            }

        } catch (\Exception $e) {
            $this->logService->warning('Error searching by custom field', [
                'field' => $fieldName,
                'value' => $value,
                'error' => $e->getMessage()
            ]);
        }

        return null;
    }

    /**
     * Set custom field value
     */
    protected function setCustomField(Contact $contact, string $fieldName, $value): void
    {
        try {
            // Abordagem 1: Campo direto na tabela
            if (in_array($fieldName, $contact->getFillable()) || $contact->hasAttribute($fieldName)) {
                $contact->{$fieldName} = $value;
                $contact->save();
                return;
            }

            // Abordagem 2: Usar método customFields se existir
            if (method_exists($contact, 'setCustomField')) {
                $contact->setCustomField($fieldName, $value);
                return;
            }

            // Abordagem 3: Usar meta se existir
            if (method_exists($contact, 'setMeta')) {
                $contact->setMeta($fieldName, $value);
                return;
            }

            // Abordagem 4: JSON field
            $customFields = $contact->custom_fields ?? [];
            $customFields[$fieldName] = $value;
            $contact->custom_fields = $customFields;
            $contact->save();

        } catch (\Exception $e) {
            $this->logService->error('Failed to set custom field', [
                'contact_id' => $contact->id,
                'field' => $fieldName,
                'value' => $value,
                'error' => $e->getMessage()
            ]);
        }
    }

    /**
     * Get custom field value
     */
    protected function getCustomField(Contact $contact, string $fieldName)
    {
        try {
            // Abordagem 1: Campo direto
            if ($contact->hasAttribute($fieldName)) {
                return $contact->{$fieldName};
            }

            // Abordagem 2: Método getCustomField se existir
            if (method_exists($contact, 'getCustomField')) {
                return $contact->getCustomField($fieldName);
            }

            // Abordagem 3: Meta se existir
            if (method_exists($contact, 'getMeta')) {
                return $contact->getMeta($fieldName);
            }

            // Abordagem 4: JSON field
            $customFields = $contact->custom_fields ?? [];
            return $customFields[$fieldName] ?? null;

        } catch (\Exception $e) {
            $this->logService->warning('Failed to get custom field', [
                'contact_id' => $contact->id,
                'field' => $fieldName,
                'error' => $e->getMessage()
            ]);
            return null;
        }
    }

    /**
     * Sync contact phones
     */
    protected function syncContactPhones(Contact $contact, array $chatwootContact): void
    {
        if (empty($chatwootContact['phone_number'])) {
            return;
        }

        $phoneNumber = $chatwootContact['phone_number'];
        
        // Verificar se o telefone já existe
        $existingPhone = $contact->phones()->where('number', $phoneNumber)->first();
        
        if (!$existingPhone) {
            // Adicionar novo telefone usando o enum correto
            $contact->phones()->create([
                'number' => $phoneNumber,
                'type' => PhoneType::mobile->value // Usar o valor do enum
            ]);
            
            $this->logService->info('Phone added to contact', [
                'contact_id' => $contact->id,
                'phone' => $phoneNumber,
                'type' => PhoneType::mobile->value
            ]);
        }
    }

    /**
     * Sync contact from CRM to Chatwoot
     */
    public function syncContactToChatwoot(Contact $contact): ?array
    {
        try {
            $chatwootId = $this->getCustomField($contact, 'cf_chatwootid_contato');
            $contactData = $this->mapCRMContactToChatwoot($contact);

            if ($chatwootId) {
                // Atualizar contato existente no Chatwoot
                $result = $this->apiService->updateContact($chatwootId, $contactData);
                $this->logService->info('Contact updated in Chatwoot', [
                    'contact_id' => $contact->id,
                    'chatwoot_id' => $chatwootId
                ]);
            } else {
                // Criar novo contato no Chatwoot
                $result = $this->apiService->createContact($contactData);
                
                if (isset($result['payload']['contact']['id'])) {
                    $this->setCustomField($contact, 'cf_chatwootid_contato', $result['payload']['contact']['id']);
                }
                
                $this->logService->info('Contact created in Chatwoot', [
                    'contact_id' => $contact->id,
                    'chatwoot_id' => $result['payload']['contact']['id'] ?? null
                ]);
            }

            return $result;

        } catch (\Exception $e) {
            $this->logService->error('Failed to sync contact to Chatwoot', [
                'contact_id' => $contact->id,
                'error' => $e->getMessage()
            ]);
            return null;
        }
    }

    /**
     * Map Chatwoot contact to CRM format
     */
    protected function mapChatwootContactToCRM(array $chatwootContact): array
    {
        $names = $this->parseFullName($chatwootContact['name'] ?? '');
        
        $data = [
            'first_name' => $names['first_name'],
            'last_name' => $names['last_name'],
            'email' => $chatwootContact['email'] ?? null,
            'user_id' => 1, // Admin user
        ];

        // Custom attributes do Chatwoot - serão definidos via setCustomField
        // Não incluir no array principal para evitar erros de campos não reconhecidos

        return array_filter($data, function($value) {
            return $value !== null && $value !== '';
        });
    }

    /**
     * Map CRM contact to Chatwoot format
     */
    protected function mapCRMContactToChatwoot(Contact $contact): array
    {
        $data = [
            'name' => $contact->display_name,
            'email' => $contact->email,
        ];

        // Telefone principal
        $primaryPhone = $contact->phones()->first();
        if ($primaryPhone) {
            $data['phone_number'] = $primaryPhone->number;
        }

        // Custom attributes
        $customAttributes = [];
        
        // Empresa
        if ($contact->companies()->exists()) {
            $company = $contact->companies()->first();
            $customAttributes['company'] = $company->name;
        }

        if (!empty($customAttributes)) {
            $data['custom_attributes'] = $customAttributes;
        }

        return $data;
    }

    /**
     * Clean phone number for search
     */
    protected function cleanPhoneNumber(string $phone): string
    {
        return preg_replace('/[^0-9]/', '', $phone);
    }

    /**
     * Parse full name into first and last name
     */
    protected function parseFullName(string $fullName): array
    {
        $parts = explode(' ', trim($fullName), 2);
        
        return [
            'first_name' => $parts[0] ?? '',
            'last_name' => $parts[1] ?? ''
        ];
    }

    // ... resto dos métodos permanecem iguais ...
    
    /**
     * Sync all contacts from Chatwoot
     */
    public function syncAllContactsFromChatwoot(): array
    {
        $results = [
            'total' => 0,
            'created' => 0,
            'updated' => 0,
            'errors' => 0
        ];

        try {
            $page = 1;
            $hasMore = true;

            while ($hasMore) {
                $this->logService->info("Syncing contacts from Chatwoot - Page {$page}");
                
                $response = $this->apiService->getContacts($page);
                $contacts = $response['payload'] ?? $response['data'] ?? [];

                if (empty($contacts)) {
                    $hasMore = false;
                    continue;
                }

                foreach ($contacts as $chatwootContact) {
                    $results['total']++;
                    
                    // Verificar se já existe
                    $existingContact = $this->findExistingContact($chatwootContact);
                    
                    $contact = $this->syncContactToCRM($chatwootContact);
                    
                    if ($contact) {
                        if ($existingContact) {
                            $results['updated']++;
                        } else {
                            $results['created']++;
                        }
                    } else {
                        $results['errors']++;
                    }
                }

                // Verificar se há mais páginas
                $hasMore = isset($response['meta']['has_next_page']) ? $response['meta']['has_next_page'] : false;
                $page++;

                // Limite de segurança
                if ($page > 100) {
                    $this->logService->warning('Sync stopped at page 100 for safety');
                    break;
                }
            }

            $this->logService->info('Bulk contact sync from Chatwoot completed', $results);
            return $results;

        } catch (\Exception $e) {
            $this->logService->error('Bulk contact sync from Chatwoot failed', [
                'results' => $results,
                'error' => $e->getMessage()
            ]);
            return $results;
        }
    }

    /**
     * Sync all contacts to Chatwoot
     */
    public function syncAllContactsToChatwoot(): array
    {
        $results = [
            'total' => 0,
            'created' => 0,
            'updated' => 0,
            'errors' => 0
        ];

        try {
            // Buscar contatos que têm email ou telefone
            $contacts = Contact::where(function($query) {
                $query->whereNotNull('email')
                      ->orWhereHas('phones');
            })->get();

            foreach ($contacts as $contact) {
                $results['total']++;
                
                $chatwootId = $this->getCustomField($contact, 'cf_chatwootid_contato');
                
                $result = $this->syncContactToChatwoot($contact);
                
                if ($result) {
                    if ($chatwootId) {
                        $results['updated']++;
                    } else {
                        $results['created']++;
                    }
                } else {
                    $results['errors']++;
                }
            }

            $this->logService->info('Bulk contact sync to Chatwoot completed', $results);
            return $results;

        } catch (\Exception $e) {
            $this->logService->error('Bulk contact sync to Chatwoot failed', [
                'results' => $results,
                'error' => $e->getMessage()
            ]);
            return $results;
        }
    }
}