<?php

namespace App\Controllers;

use App\Models\Company;
use App\Models\Orders;
use App\Models\Products;
use App\Models\Avance;
use App\Models\User; // Ajout pour récupérer les emails DAF/Directrice

class AvanceController extends AdminController
{
    private $pageTitle = 'Avances';

    public function __construct()
    {
        parent::__construct();
    }

    public function index()
    {
        $this->verifyRole('viewAvance');
        $data['page_title'] = $this->pageTitle;
        $Products = new Products();
        $session = session();
        $users   = $session->get('user');
        $store_id = $users['store_id'];
        $data['products'] = $Products->getProductDataStore($store_id);
        return $this->render_template('avances/avance', $data);
    }

    private function isAdmin($user)
    {
        return in_array($user['group_name'], ['Conseil', 'Direction']);
    }

    private function isCommerciale($user)
    {
        return in_array($user['group_name'], ['COMMERCIALE']);
    }

    private function isCaissier($user)
    {
        return in_array($user['group_name'], ['Caissier']);
    }

    private function buildActionButtons($value, $isAdmin, $isOwner)
    {
        $buttons = '';
        
        if (in_array('updateAvance', $this->permission) && ($isAdmin || $isOwner)) {
            $buttons .= '<button type="button" class="btn btn-default" onclick="editFunc(' . $value['avance_id'] . ')" title="Modifier">'
                . '<i class="fa fa-pencil"></i></button> ';
        }
        
        if (in_array('deleteAvance', $this->permission) && ($isAdmin || $isOwner)) {
            $buttons .= '<button type="button" class="btn btn-danger" onclick="removeFunc(' . $value['avance_id'] . ',' . $value['product_id'] . ')" title="Supprimer">'
                . '<i class="fa fa-trash"></i></button> ';
        }
        
        if (in_array('viewAvance', $this->permission) && !$isAdmin) {
            $buttons .= '<a href="#" data-order-id="' . $value['avance_id'] . '" class="btn btn-default btn-view" title="Voir">'
                . '<i class="fa fa-eye"></i></a>';
        }
        
        return $buttons;
    }

    private function buildDataRow($value, $product, $isAdmin, $isCommerciale, $isCaissier, $buttons)
    {
        $date_time = date('d-m-Y h:i a', strtotime($value['avance_date']));
        
        if ($isAdmin) {
            return [
                $value['customer_name'],
                $value['customer_phone'],
                $value['customer_address'],
                $product->getProductNameById($value['product_id']),
                number_format((int)$value['gross_amount'], 0, ',', ' '),
                number_format((int)$value['avance_amount'], 0, ',', ' '),
                number_format((int)$value['amount_due'], 0, ',', ' '),
                $date_time,
                $buttons,
            ];
        } elseif ($isCommerciale || $isCaissier) {
            return [
                $value['avance_id'],
                $product->getProductNameById($value['product_id']),
                number_format((int)$value['avance_amount'], 0, ',', ' '),
                number_format((int)$value['amount_due'], 0, ',', ' '),
                $date_time,
                $buttons,
            ];
        }
        
        return [];
    }

    private function fetchAvanceDataGeneric($methodName = 'getAllAvanceData')
    {
        helper(['url', 'form']);
        $Avance = new Avance();
        $product = new Products();
        $result = ['data' => []];
        
        $data = $Avance->$methodName();
        $session = session();
        $users = $session->get('user');
        
        $isAdmin = $this->isAdmin($users);
        $isCommerciale = $this->isCommerciale($users);
        $isCaissier = $this->isCaissier($users);

        foreach ($data as $key => $value) {
            $isOwner = $users['id'] === $value['user_id'];
            
            $buttons = $this->buildActionButtons($value, $isAdmin, $isOwner);
            
            $row = $this->buildDataRow($value, $product, $isAdmin, $isCommerciale, $isCaissier, $buttons);
            
            if (!empty($row)) {
                $result['data'][] = $row;
            }
        }

        return $this->response->setJSON($result);
    }

    public function fetchAvanceData()
    {
        return $this->fetchAvanceDataGeneric('getAllAvanceData');
    }

    public function fetchAvanceBecameOrder()
    {
        return $this->fetchAvanceDataGeneric('getAllAvanceData1');
    }

    public function fetcheExpiredAvance()
    {
        return $this->fetchAvanceDataGeneric('getAllAvanceData2');
    }

    /**
     * Méthode pour vérifier et envoyer des emails d'alerte 3 jours avant deadline
     * À exécuter via CRON job quotidiennement
     */
    public function checkDeadlineAlerts()
    {
        try {
            $Avance = new Avance();
            $Products = new Products();
            
            // Récupérer toutes les avances actives non converties en commandes
            $avances = $Avance->getAvancesNearDeadline(3); // 3 jours avant deadline
            
            if (!empty($avances)) {
                foreach ($avances as $avance) {
                    // Vérifier si l'email n'a pas déjà été envoyé pour cette avance
                    if (!$this->hasEmailBeenSent($avance['avance_id'])) {
                        $this->sendDeadlineAlert($avance, $Products);
                        $this->markEmailAsSent($avance['avance_id']);
                    }
                }
            }
            
            return $this->response->setJSON([
                'success' => true,
                'messages' => 'Vérification des alertes terminée',
                'alerts_sent' => count($avances)
            ]);
        } catch (\Exception $e) {
            log_message('error', "Erreur vérification deadline: " . $e->getMessage());
            return $this->response->setJSON([
                'success' => false,
                'messages' => 'Erreur lors de la vérification des deadlines'
            ]);
        }
    }

    /**
     * Envoyer un email d'alerte au DAF et à la Directrice
     */
    private function sendDeadlineAlert($avance, $Products)
    {
        try {
            $email = \Config\Services::email();
            
            // Configuration email (à adapter selon votre config)
            $email->setFrom('noreply@yourcompany.com', 'Système de Gestion des Avances');
            
            // Récupérer les emails du DAF et de la Directrice
            $recipients = $this->getDAFAndDirectriceEmails($avance['store_id']);
            $email->setTo($recipients);
            
            $email->setSubject('⚠️ ALERTE: Avance arrive à échéance dans 3 jours');
            
            // Récupérer le nom du produit
            $productName = $Products->getProductNameById($avance['product_id']);
            
            // Calcul des jours restants
            $deadline = new \DateTime($avance['deadline']);
            $today = new \DateTime();
            $daysRemaining = $today->diff($deadline)->days;
            
            // Corps de l'email
            $message = $this->buildEmailMessage($avance, $productName, $daysRemaining);
            $email->setMessage($message);
            
            // Envoyer l'email
            if ($email->send()) {
                log_message('info', "Email d'alerte envoyé pour l'avance ID: " . $avance['avance_id']);
                return true;
            } else {
                log_message('error', "Échec envoi email pour avance ID: " . $avance['avance_id'] . " - " . $email->printDebugger());
                return false;
            }
        } catch (\Exception $e) {
            log_message('error', "Erreur envoi email alerte: " . $e->getMessage());
            return false;
        }
    }

    /**
     * Récupérer les emails du DAF et de la Directrice
     */
    private function getDAFAndDirectriceEmails($store_id)
    {
        $User = new User();
        $emails = [];
        
        // Récupérer les utilisateurs avec les rôles DAF et Direction pour le store donné
        $dafUsers = $User->getUsersByRole('DAF', $store_id);
        $directionUsers = $User->getUsersByRole('Direction', $store_id);
        
        // Extraire les emails
        foreach ($dafUsers as $user) {
            if (!empty($user['email'])) {
                $emails[] = $user['email'];
            }
        }
        
        foreach ($directionUsers as $user) {
            if (!empty($user['email'])) {
                $emails[] = $user['email'];
            }
        }
        
        // Si aucun email trouvé, utiliser des emails par défaut (à configurer)
        if (empty($emails)) {
            $emails = [
                'daf@yourcompany.com',
                'direction@yourcompany.com'
            ];
        }
        
        return array_unique($emails); // Éviter les doublons
    }

    /**
     * Construire le message de l'email
     */
    private function buildEmailMessage($avance, $productName, $daysRemaining)
    {
        $typeAvance = strtoupper($avance['type_avance']);
        $deadlineFormatted = date('d/m/Y', strtotime($avance['deadline']));
        $avanceDateFormatted = date('d/m/Y à H:i', strtotime($avance['avance_date']));
        $amountDueFormatted = number_format($avance['amount_due'], 0, ',', ' ') . ' FCFA';
        
        $urgencyClass = $daysRemaining <= 1 ? 'style="color: red; font-weight: bold;"' : '';
        
        return "
        <html>
        <head>
            <style>
                .container { font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; }
                .header { background-color: #f8f9fa; padding: 20px; text-align: center; border-radius: 5px; }
                .alert { background-color: #fff3cd; border: 1px solid #ffeaa7; padding: 15px; margin: 20px 0; border-radius: 5px; }
                .details { background-color: #f8f9fa; padding: 15px; margin: 10px 0; border-radius: 5px; }
                .urgent { color: #dc3545; font-weight: bold; }
                .footer { margin-top: 30px; padding: 15px; background-color: #e9ecef; border-radius: 5px; font-size: 12px; }
            </style>
        </head>
        <body>
            <div class='container'>
                <div class='header'>
                    <h2>⚠️ ALERTE DEADLINE AVANCE</h2>
                </div>
                
                <div class='alert'>
                    <p><strong " . $urgencyClass . ">Une avance arrive à échéance dans {$daysRemaining} jour(s) !</strong></p>
                </div>
                
                <div class='details'>
                    <h3>Détails de l'avance :</h3>
                    <ul>
                        <li><strong>ID Avance :</strong> #{$avance['avance_id']}</li>
                        <li><strong>Type d'avance :</strong> {$typeAvance}</li>
                        <li><strong>Client :</strong> {$avance['customer_name']}</li>
                        <li><strong>Téléphone :</strong> {$avance['customer_phone']}</li>
                        <li><strong>Adresse :</strong> {$avance['customer_address']}</li>
                        <li><strong>CIN :</strong> {$avance['customer_cin']}</li>
                        <li><strong>Produit :</strong> {$productName}</li>
                        <li><strong>Montant restant dû :</strong> <span class='urgent'>{$amountDueFormatted}</span></li>
                        <li><strong>Date avance :</strong> {$avanceDateFormatted}</li>
                        <li><strong>Date limite :</strong> <span class='urgent'>{$deadlineFormatted}</span></li>
                    </ul>
                </div>
                
                <div class='alert'>
                    <p><strong>Action requise :</strong></p>
                    <p>Veuillez contacter le client pour régulariser le paiement avant l'échéance ou prendre les mesures appropriées.</p>
                </div>
                
                <div class='footer'>
                    <p>Cet email a été généré automatiquement par le système de gestion des avances.</p>
                    <p>Date d'envoi : " . date('d/m/Y à H:i') . "</p>
                </div>
            </div>
        </body>
        </html>
        ";
    }

    /**
     * Vérifier si un email a déjà été envoyé pour cette avance
     */
    private function hasEmailBeenSent($avance_id)
    {
        $db = \Config\Database::connect();
        $query = $db->query("SELECT id FROM email_alerts WHERE avance_id = ? AND alert_type = 'deadline_3days'", [$avance_id]);
        return $query->getNumRows() > 0;
    }

    /**
     * Marquer l'email comme envoyé
     */
    private function markEmailAsSent($avance_id)
    {
        $db = \Config\Database::connect();
        $data = [
            'avance_id' => $avance_id,
            'alert_type' => 'deadline_3days',
            'sent_date' => date('Y-m-d H:i:s'),
            'status' => 'sent'
        ];
        
        $db->table('email_alerts')->insert($data);
    }

    public function createAvance()
    {
        $this->verifyRole('createAvance');

        if ($this->request->getMethod() !== 'post') {
            return $this->response->setJSON([
                'success' => false,
                'messages' => 'Méthode non autorisée'
            ]);
        }

        try {
            $session = session();
            $users = $session->get('user');
            
            $Avance = new Avance();
            $Products = new Products();
            $Notification = new NotificationController();

            $validation = \Config\Services::validation();
            $validation->setRules([
                'customer_name_avance' => 'required|min_length[2]',
                'customer_phone_avance' => 'required',
                'customer_address_avance' => 'required',
                'customer_cin_avance' => 'required',
                'id_product' => 'required|numeric',
                'avance_amount' => 'required|numeric|greater_than[0]',
                'type_avance' => 'required|in_list[terre,mere]'
            ]);

            if (!$validation->withRequest($this->request)->run()) {
                return $this->response->setJSON([
                    'success' => false,
                    'messages' => 'Données invalides: ' . implode(', ', $validation->getErrors())
                ]);
            }

            $avance_date = date('Y-m-d H:i:s');

            // Calcul automatique de la deadline selon le type d'avance
            $type_avance = $this->request->getPost('type_avance');
            if ($type_avance === 'terre') {
                $deadline = date('Y-m-d', strtotime($avance_date . ' +15 days'));
            } elseif ($type_avance === 'mere') {
                $deadline = date('Y-m-d', strtotime($avance_date . ' +2 months'));
            } else {
                $deadline = null; // fallback si jamais
            }

            $data = [
                'type_avance'      => $type_avance,
                'customer_name'    => $this->request->getPost('customer_name_avance'),
                'customer_address' => $this->request->getPost('customer_address_avance'),
                'customer_phone'   => $this->request->getPost('customer_phone_avance'),
                'customer_cin'     => $this->request->getPost('customer_cin_avance'),
                'avance_date'      => $avance_date,
                'deadline'         => $deadline,
                'user_id'          => $users['id'],
                'store_id'         => $users['store_id'],
                'product_id'       => (int)$this->request->getPost('id_product'),
                'gross_amount'     => (float)$this->request->getPost('gross_amount'),
                'avance_amount'    => (float)$this->request->getPost('avance_amount'),
                'amount_due'       => (float)$this->request->getPost('amount_due'),
                'is_order'         => 0,
                'active'           => 1,
            ];

            if ($avance_id = $Avance->createAvance($data)) {
                $Products->update($data['product_id'], ['product_sold' => 1]);
                
                $Notification->createNotification(
                    'Une nouvelle avance a été créée', 
                    "Conseil", 
                    (int)$users['store_id'], 
                    'avances'
                );
                
                return $this->response->setJSON([
                    'success' => true,
                    'messages' => 'Avance créée avec succès !',
                    'avance_id' => $avance_id
                ]);
            } else {
                return $this->response->setJSON([
                    'success' => false,
                    'messages' => 'Erreur lors de la création de l\'avance'
                ]);
            }
        } catch (\Exception $e) {
            log_message('error', "Erreur création avance: " . $e->getMessage());
            return $this->response->setJSON([
                'success' => false,
                'messages' => 'Une erreur interne est survenue'
            ]);
        }
    }

    public function updateAvance(int $id)
    {
        $this->verifyRole('updateAvance');

        if ($this->request->getMethod() !== 'post') {
            return $this->response->setJSON([
                'success' => false,
                'messages' => 'Méthode non autorisée'
            ]);
        }

        try {
            $session = session();
            $users = $session->get('user');
            
            $Avance = new Avance();
            $Products = new Products();
            $Orders = new Orders();
            $Company = new Company();
            $Notification = new NotificationController();

            $validation = \Config\Services::validation();
            $validation->setRules([
                'customer_name_avance_edit' => 'required|min_length[2]',
                'customer_phone_avance_edit' => 'required',
                'customer_address_avance_edit' => 'required',
                'customer_cin_avance_edit' => 'required',
                'id_product_edit' => 'required|numeric',
                'avance_amount_edit' => 'required|numeric|greater_than[0]',
                'type_avance_edit' => 'required|in_list[terre,mere]'
            ]);

            if (!$validation->withRequest($this->request)->run()) {
                return $this->response->setJSON([
                    'success' => false,
                    'messages' => 'Données invalides: ' . implode(', ', $validation->getErrors())
                ]);
            }

            // Récupérer la date de création actuelle de l'avance pour recalculer deadline
            $currentAvance = $Avance->find($id);
            if (!$currentAvance) {
                return $this->response->setJSON([
                    'success' => false,
                    'messages' => 'Avance introuvable.'
                ]);
            }
            $avance_date = $currentAvance['avance_date'];

            // Calcul automatique deadline selon le type d'avance
            $type_avance = $this->request->getPost('type_avance_edit');
            if ($type_avance === 'terre') {
                $deadline = date('Y-m-d', strtotime($avance_date . ' +15 days'));
            } elseif ($type_avance === 'mere') {
                $deadline = date('Y-m-d', strtotime($avance_date . ' +2 months'));
            } else {
                $deadline = null;
            }

            $data = [
                'type_avance'      => $type_avance,
                'customer_name'    => $this->request->getPost('customer_name_avance_edit'),
                'customer_address' => $this->request->getPost('customer_address_avance_edit'),
                'customer_phone'   => $this->request->getPost('customer_phone_avance_edit'),
                'customer_cin'     => $this->request->getPost('customer_cin_avance_edit'),
                'gross_amount'     => (float)$this->request->getPost('gross_amount_edit'),
                'avance_amount'    => (float)$this->request->getPost('avance_amount_edit'),
                'amount_due'       => (float)$this->request->getPost('amount_due_edit'),
                'product_id'       => (int)$this->request->getPost('id_product_edit'),
                'deadline'         => $deadline,
            ];

            $amount_due = $data['amount_due'];

            if ($amount_due <= 0) {
                $bill_no = 'BILPR-' . strtoupper(substr(md5(uniqid(mt_rand(), true)), 0, 4));
                $company = $Company->getCompanyData(1);
                
                $service_charge_rate = $company['service_charge_value'] ?? 0;
                $vat_charge_rate = $company['vat_charge_value'] ?? 0;
                $gross_amount = $data['gross_amount'];
                $vat_charge = ($gross_amount / 100) * $vat_charge_rate;

                $order_data = [
                    'bill_no'             => $bill_no,
                    'customer_name'       => $data['customer_name'],
                    'customer_address'    => $data['customer_address'],
                    'customer_phone'      => $data['customer_phone'],
                    'customer_cin'        => $data['customer_cin'],
                    'gross_amount'        => $gross_amount,
                    'net_amount'          => $gross_amount,
                    'date_time'           => date('Y-m-d H:i:s'),
                    'service_charge_rate' => $service_charge_rate,
                    'vat_charge_rate'     => $vat_charge_rate,
                    'vat_charge'          => $vat_charge,
                    'discount'            => 0,
                    'paid_status'         => 1,
                    'user_id'             => $users['id'],
                    'store_id'            => $users['store_id'],
                    'amount_value'        => $gross_amount,
                    'rate_value'          => $gross_amount,
                ];

                $product_id = [$data['product_id']];

                if ($Orders->create($order_data, $product_id)) {
                    $Avance->updateAvance($id, ['is_order' => 1]);
                    $Notification->createNotification(
                        'Une avance a été convertie en commande', 
                        "Conseil", 
                        (int)$users['store_id'], 
                        'orders'
                    );

                    return $this->response->setJSON([
                        'success' => true,
                        'messages' => 'Avance convertie en commande avec succès.'
                    ]);
                } else {
                    return $this->response->setJSON([
                        'success' => false,
                        'messages' => 'Erreur lors de la conversion de l\'avance en commande'
                    ]);
                }
            } else {
                if ($Avance->updateAvance($id, $data)) {
                    return $this->response->setJSON([
                        'success' => true,
                        'messages' => 'Avance mise à jour avec succès.'
                    ]);
                } else {
                    return $this->response->setJSON([
                        'success' => false,
                        'messages' => 'Erreur lors de la mise à jour de l\'avance.'
                    ]);
                }
            }
        } catch (\Exception $e) {
            log_message('error', "Erreur mise à jour avance: " . $e->getMessage());
            return $this->response->setJSON([
                'success' => false,
                'messages' => 'Une erreur interne est survenue'
            ]);
        }
    }

    public function removeAvance()
    {
        $this->verifyRole('deleteAvance');
        
        try {
            $avance_id = $this->request->getPost('avance_id');
            $product_id = $this->request->getPost('product_id');

            if (!$avance_id || !$product_id) {
                return $this->response->setJSON([
                    'success' => false,
                    'messages' => 'Données manquantes pour la suppression'
                ]);
            }

            $Avance = new Avance();
            $Products = new Products();

            if ($Avance->removeAvance($avance_id)) {
                $Products->update($product_id, ['product_sold' => 0]);
                
                return $this->response->setJSON([
                    'success' => true,
                    'messages' => "Avance supprimée avec succès. Le produit peut être réservé à nouveau."
                ]);
            } else {
                return $this->response->setJSON([
                    'success' => false,
                    'messages' => "Erreur lors de la suppression de l'avance"
                ]);
            }
        } catch (\Exception $e) {
            log_message('error', "Erreur suppression avance: " . $e->getMessage());
            return $this->response->setJSON([
                'success' => false,
                'messages' => 'Une erreur interne est survenue'
            ]);
        }
    }

    public function fetchSingleAvance($avance_id)
    {
        $this->verifyRole('updateAvance');

        try {
            if (!$avance_id || !is_numeric($avance_id)) {
                return $this->response->setStatusCode(400)->setJSON([
                    'error' => 'ID d\'avance invalide'
                ]);
            }

            $avanceModel = new Avance();
            $data = $avanceModel->fetchSingleAvance($avance_id);

            if (!$data) {
                return $this->response->setStatusCode(404)->setJSON([
                    'error' => 'Avance non trouvée'
                ]);
            }

            return $this->response->setJSON($data);
        } catch (\Exception $e) {
            log_message('error', "Erreur récupération avance: " . $e->getMessage());
            return $this->response->setStatusCode(500)->setJSON([
                'error' => 'Erreur interne lors de la récupération de l\'avance'
            ]);
        }
    }
}