<?php

namespace App\Models;

use CodeIgniter\Model;

class NotificationModel extends Model
{
    protected $table = 'notifications';
    protected $primaryKey = 'id';
    
    protected $useAutoIncrement = true;
    
    protected $returnType = 'array';
    protected $useSoftDeletes = false;
    
    protected $allowedFields = [
        'user_id',
        'title',
        'body',
        'data',
        'target',
        'status',
        'read_at',
        'created_by'
    ];
    
    protected $useTimestamps = true;
    protected $createdField = 'created_at';
    protected $updatedField = null;
    
    protected $validationRules = [
        'title' => 'required',
        'body' => 'required',
        'status' => 'permit_empty|in_list[sent,delivered,read,failed]',
    ];
    
    /**
     * Kurucu metod - tabloyu kontrol et
     */
    public function __construct()
    {
        parent::__construct();
        
        // Tablo kontrol et ve oluştur/güncelle
        $this->checkTableColumns();
    }
    
    /**
     * Tablo sütunlarını kontrol et ve eksikse oluştur
     */
    private function checkTableColumns()
    {
        $db = \Config\Database::connect();
        $forge = \Config\Database::forge();
        
        // Tablo var mı kontrol et
        $tables = $db->listTables();
        
        if (!in_array($this->table, $tables)) {
            // Tablo yoksa oluştur
            $forge->addField([
                'id' => [
                    'type' => 'INT',
                    'constraint' => 11,
                    'unsigned' => true,
                    'auto_increment' => true
                ],
                'user_id' => [
                    'type' => 'INT',
                    'constraint' => 11,
                    'null' => true
                ],
                'title' => [
                    'type' => 'VARCHAR',
                    'constraint' => 255,
                    'null' => false
                ],
                'body' => [
                    'type' => 'TEXT',
                    'null' => false
                ],
                'data' => [
                    'type' => 'TEXT',
                    'null' => true
                ],
                'target' => [
                    'type' => 'VARCHAR',
                    'constraint' => 100,
                    'null' => true
                ],
                'status' => [
                    'type' => 'ENUM',
                    'constraint' => ['sent', 'delivered', 'read', 'failed'],
                    'default' => 'sent'
                ],
                'read_at' => [
                    'type' => 'DATETIME',
                    'null' => true
                ],
                'created_by' => [
                    'type' => 'INT',
                    'constraint' => 11,
                    'null' => true
                ],
                'created_at' => [
                    'type' => 'DATETIME',
                    'null' => true
                ],
                'updated_at' => [
                    'type' => 'DATETIME',
                    'null' => true
                ]
            ]);
            
            $forge->addKey('id', true);
            $forge->addKey('user_id');
            $forge->addKey('status');
            $forge->addKey('created_at');
            
            $forge->createTable($this->table);
            
            log_message('info', "Tablo '{$this->table}' oluşturuldu");
        }
    }
    
    /**
     * Add notification record
     * 
     * @param array $data Notification data
     * @return int|false New record ID or false on failure
     */
    public function addNotification($data)
    {
        try {
            // Set default status if not provided
            if (!isset($data['status'])) {
                $data['status'] = 'sent';
            }
            
            // Convert data field to JSON if it's an array
            if (isset($data['data']) && is_array($data['data'])) {
                $data['data'] = json_encode($data['data']);
            }
            
            return $this->insert($data);
        } catch (\Exception $e) {
            log_message('error', 'Error adding notification: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Get user notification history
     * 
     * @param int $userId User ID
     * @param int $limit Maximum number of notifications
     * @param int $offset Offset for pagination
     * @param string $targetType Filter by target type
     * @return array Notification history
     */
    public function getNotificationHistory($userId, $limit = 50, $offset = 0, $targetType = null)
    {
        $query = $this->where('user_id', $userId)
                     ->orderBy('created_at', 'DESC');
        
        // Apply target type filter if provided
        if ($targetType !== null) {
            $query->like('target', $targetType . '%');
        }
        
        $notifications = $query->limit($limit, $offset)->findAll();
        
        // Process notifications - decode JSON data field
        foreach ($notifications as &$notification) {
            if (isset($notification['data']) && !empty($notification['data'])) {
                try {
                    $notification['data_decoded'] = json_decode($notification['data'], true);
                } catch (\Exception $e) {
                    $notification['data_decoded'] = null;
                }
            }
            
            // Format dates
            if (!empty($notification['created_at'])) {
                $notification['created_at_formatted'] = date('d.m.Y H:i', strtotime($notification['created_at']));
            }
            
            if (!empty($notification['read_at'])) {
                $notification['read_at_formatted'] = date('d.m.Y H:i', strtotime($notification['read_at']));
            }
        }
        
        return $notifications;
    }
    
    /**
     * Get notification count
     * 
     * @param int $userId User ID
     * @param string $targetType Filter by target type
     * @return int Number of notifications
     */
    public function getNotificationCount($userId, $targetType = null)
    {
        $query = $this->where('user_id', $userId);
        
        // Apply target type filter if provided
        if ($targetType !== null) {
            $query->like('target', $targetType . '%');
        }
        
        return $query->countAllResults();
    }
    
    /**
     * Mark notification as read
     * 
     * @param int $notificationId Notification ID
     * @return bool Success status
     */
    public function markAsRead($notificationId)
    {
        return $this->update($notificationId, [
            'status' => 'read',
            'read_at' => date('Y-m-d H:i:s')
        ]);
    }
    
    /**
     * Mark all user notifications as read
     * 
     * @param int $userId User ID
     * @return bool Success status
     */
    public function markAllAsRead($userId)
    {
        return $this->where('user_id', $userId)
                   ->where('status !=', 'read')
                   ->set([
                       'status' => 'read',
                       'read_at' => date('Y-m-d H:i:s')
                   ])
                   ->update();
    }
    
    /**
     * Get unread notification count
     * 
     * @param int $userId User ID
     * @return int Number of unread notifications
     */
    public function getUnreadCount($userId)
    {
        return $this->where('user_id', $userId)
                   ->where('status !=', 'read')
                   ->countAllResults();
    }
    
    /**
     * Delete notification
     * 
     * @param int $notificationId Notification ID
     * @param int $userId User ID for security check
     * @return bool Success status
     */
    public function deleteNotification($notificationId, $userId)
    {
        return $this->where('id', $notificationId)
                   ->where('user_id', $userId)
                   ->delete();
    }
    
    /**
     * Get notification statistics
     * 
     * @param int $days Number of days to look back
     * @return array Notification statistics
     */
    public function getNotificationStats($days = 30)
    {
        $db = \Config\Database::connect();
        
        // Total count
        $totalCount = $this->countAllResults();
        
        // Status breakdown
        $statusQuery = $this->select('status, COUNT(*) as total')
                          ->groupBy('status')
                          ->findAll();
                          
        $status = [];
        foreach ($statusQuery as $row) {
            $status[$row['status']] = (int)$row['total'];
        }
        
        // Daily trend for the last X days
        $startDate = date('Y-m-d', strtotime("-$days days"));
        $trendQuery = $db->query("
            SELECT 
                DATE(created_at) as date,
                COUNT(*) as total,
                SUM(CASE WHEN status = 'sent' THEN 1 ELSE 0 END) as sent,
                SUM(CASE WHEN status = 'delivered' THEN 1 ELSE 0 END) as delivered,
                SUM(CASE WHEN status = 'read' THEN 1 ELSE 0 END) as read,
                SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed
            FROM 
                {$this->table}
            WHERE 
                created_at >= '$startDate'
            GROUP BY 
                DATE(created_at)
            ORDER BY 
                date DESC
        ");
        
        $trends = $trendQuery->getResultArray();
        
        return [
            'total' => $totalCount,
            'status' => $status,
            'trends' => $trends
        ];
    }
    
    /**
     * EnquiryService'den gelen bildirimleri gönderir
     * 
     * @param int $enquiryId Enquiry ID
     * @param string $title Bildirim başlığı
     * @param string $body Bildirim içeriği
     * @param array $data Bildirim ek bilgileri
     * @param int|null $userId Hedef kullanıcı ID (yoksa tüm adminlere gönderilir)
     * @return bool Başarı durumu
     */
    public function sendEnquiryNotification($enquiryId, $title, $body, $data = [], $userId = null)
    {
        try {
            $notificationService = service('NotificationService');
            $userModel = model('App\Models\UserModel');
            
            // Ek verileri düzenle
            $data['enquiry_id'] = $enquiryId;
            $data['notification_type'] = 'enquiry';
            $data['click_action'] = 'OPEN_ENQUIRY_DETAIL';
            
            $success = true;
            $notificationsSent = 0;
            $notificationsRecorded = 0;
            
            if ($userId) {
                // Belirli bir kullanıcıya gönder
                
                // Bildirim kimliği oluştur
                $notificationId = $this->addNotification([
                    'user_id' => $userId,
                    'title' => $title,
                    'body' => $body,
                    'data' => json_encode($data),
                    'target' => 'enquiry',
                    'status' => 'sent'
                ]);
                
                if ($notificationId) {
                    $notificationsRecorded++;
                }
                
                // Kullanıcının tüm cihazlarına bildirim gönder
                $devicesSent = $notificationService->sendToUser(
                    $userId,
                    $title,
                    $body,
                    $data
                );
                
                if ($devicesSent) {
                    $notificationsSent++;
                }
                
                $success = $devicesSent;
                
            } else {
                // Tüm adminlere gönder
                $admins = $userModel->where('type', 'ADMIN')->findAll();
                
                if (empty($admins)) {
                    log_message('warning', 'No admins found for enquiry notification');
                    return false;
                }
                
                foreach ($admins as $admin) {
                    // Her admin için bildirim kaydı oluştur
                    $notificationId = $this->addNotification([
                        'user_id' => $admin['id'],
                        'title' => $title,
                        'body' => $body,
                        'data' => json_encode($data),
                        'target' => 'enquiry',
                        'status' => 'sent'
                    ]);
                    
                    if ($notificationId) {
                        $notificationsRecorded++;
                    }
                    
                    // Admin'in tüm cihazlarına bildirim gönder
                    $devicesSent = $notificationService->sendToUser(
                        $admin['id'],
                        $title,
                        $body,
                        $data
                    );
                    
                    if ($devicesSent) {
                        $notificationsSent++;
                    } else {
                        $success = false;
                    }
                }
            }
            
            log_message('info', "Enquiry notifications completed - Records: $notificationsRecorded, Sent: $notificationsSent");
            
            return $notificationsSent > 0;
            
        } catch (\Exception $e) {
            log_message('error', 'Error sending enquiry notification: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Soruya cevap eklendiğinde bildirim gönder
     * 
     * @param int $enquiryId Enquiry ID
     * @param int $replyId Cevap ID
     * @param string $replierName Cevap yazan kişi
     * @param string $message Cevap içeriği
     * @param string $propertyTitle Mülk başlığı
     * @param bool $isAgent Cevap veren bir temsilci mi
     * @param int|null $agentId Temsilci ID
     * @return bool Başarı durumu
     */
    public function sendReplyNotification($enquiryId, $replyId, $replierName, $message, $propertyTitle, $isAgent = false, $agentId = null)
    {
        try {
            if ($isAgent) {
                // Temsilci cevapladıysa, adminlere tam bilgi ver
                $shortMessage = mb_strlen($message) > 100 
                    ? mb_substr($message, 0, 97) . '...' 
                    : $message;
                
                $title = 'Yeni Cevap: ' . $propertyTitle;
                $body = $replierName . ': ' . $shortMessage;
                
                $data = [
                    'enquiry_id' => $enquiryId,
                    'reply_id' => $replyId,
                    'notification_type' => 'enquiry_reply',
                    'click_action' => 'OPEN_ENQUIRY_DETAIL',
                    'property_title' => $propertyTitle
                ];
                
                // Adminlere bildirim gönder
                return $this->sendEnquiryNotification(
                    $enquiryId,
                    $title,
                    $body,
                    $data
                );
            } else {
                // Admin cevapladıysa, agent'a özel bildirim gönder
                if ($agentId) {
                    // Agent için özel bildirim - müşteri bilgileri olmadan
                    $title = $propertyTitle . ' mülkünüz için yeni bir cevap var';
                    $body = 'Mülkünüzdeki sorguya yeni bir cevap geldi';
                    
                    $data = [
                        'enquiry_id' => $enquiryId,
                        'reply_id' => $replyId,
                        'notification_type' => 'enquiry_reply_agent',
                        'click_action' => 'OPEN_ENQUIRY_DETAIL',
                        'property_title' => $propertyTitle,
                        'is_agent_notification' => true
                    ];
                    
                    return $this->sendEnquiryNotification(
                        $enquiryId,
                        $title,
                        $body,
                        $data,
                        $agentId
                    );
                }
            }
            
            return true;
            
        } catch (\Exception $e) {
            log_message('error', 'Error sending reply notification: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Get admin notification count
     * 
     * @return int Number of admin notifications
     */
    public function getAdminNotificationCount()
    {
        $userModel = model('App\Models\UserModel');
        $admins = $userModel->where('type', 'ADMIN')->findAll();
        
        $totalCount = 0;
        foreach ($admins as $admin) {
            $totalCount += $this->where('user_id', $admin['id'])->countAllResults();
        }
        
        return $totalCount;
    }
    
    /**
     * Get admin unread notification count
     * 
     * @return int Number of admin unread notifications
     */
    public function getAdminUnreadCount()
    {
        $userModel = model('App\Models\UserModel');
        $admins = $userModel->where('type', 'ADMIN')->findAll();
        
        $totalUnread = 0;
        foreach ($admins as $admin) {
            $totalUnread += $this->getUnreadCount($admin['id']);
        }
        
        return $totalUnread;
    }
    
    /**
     * Bulk mark notifications as delivered
     * 
     * @param array $notificationIds Array of notification IDs
     * @return bool Success status
     */
    public function markAsDelivered($notificationIds)
    {
        if (empty($notificationIds)) {
            return false;
        }
        
        return $this->whereIn('id', $notificationIds)
                   ->where('status', 'sent')
                   ->set(['status' => 'delivered'])
                   ->update();
    }
    
    /**
     * Clean old notifications
     * 
     * @param int $days Days to keep notifications
     * @return int Number of deleted notifications
     */
    public function cleanOldNotifications($days = 90)
    {
        try {
            $cutoffDate = date('Y-m-d H:i:s', strtotime("-{$days} days"));
            
            $count = $this->where('created_at <', $cutoffDate)->countAllResults();
            
            $this->where('created_at <', $cutoffDate)->delete();
            
            log_message('info', "Cleaned {$count} old notifications older than {$days} days");
            
            return $count;
            
        } catch (\Exception $e) {
            log_message('error', 'Error cleaning old notifications: ' . $e->getMessage());
            return 0;
        }
    }
}