<?php

class BillingCalculator {
    private $db;
    private $settings;
    
    public function __construct($db) {
        $this->db = $db;
        $this->loadSettings();
    }
    
    private function loadSettings() {
        $stmt = $this->db->query('SELECT * FROM settings LIMIT 1');
        $this->settings = $stmt->fetchArray(SQLITE3_ASSOC);
    }
    
    public function calculateInvoice($consumptionId) {
        // Get consumption and subscriber data
        $stmt = $this->db->prepare('
            SELECT c.*, s.family_members 
            FROM consumption c 
            JOIN subscribers s ON c.subscriber_id = s.id 
            WHERE c.id = :consumption_id
        ');
        $stmt->bindValue(':consumption_id', $consumptionId, SQLITE3_INTEGER);
        $result = $stmt->execute();
        $data = $result->fetchArray(SQLITE3_ASSOC);
        
        if (!$data) {
            throw new Exception('Consumption record not found');
        }
        
        // Calculate consumption value
        $consumption = $data['current_reading'] - $data['previous_reading'];
        
        // 3. مبلغ الاستهلاك - حساب السعر حسب الأشطر
        $consumption_amount = 0;
        if ($consumption == 0) {
            // إذا كان الاستهلاك منعدما فإن ثمن الاستهلاك يساوي 0
            $consumption_amount = 0;
        } else {
            // Get consumption threshold from settings
            $consumption_threshold = $this->settings['consumption_threshold'];
            
            if ($consumption > $consumption_threshold) {
                // إذا تجاوز الاستهلاك العتبة المحددة، نطبق ثمن الشطر الموافق على كامل الاستهلاك
                $tier_price = $this->db->querySingle("
                    SELECT price_per_unit 
                    FROM consumption_tiers 
                    WHERE start_range <= $consumption 
                        AND (end_range >= $consumption OR end_range IS NULL)
                    LIMIT 1
                ");
                
                if ($tier_price) {
                    $consumption_amount = $consumption * $tier_price;
                } else {
                    $consumption_amount = $this->settings['minimum_payment_amount'];
                }
            } else {
                // إذا كان الاستهلاك أقل من العتبة، نطبق حساب تصاعدي حسب الأشطر
                $tiers_stmt = $this->db->query('SELECT * FROM consumption_tiers ORDER BY start_range ASC');
                $remaining_consumption = $consumption;
                
                while ($tier = $tiers_stmt->fetchArray(SQLITE3_ASSOC)) {
                    if ($remaining_consumption <= 0) {
                        break;
                    }
                    
                    $tier_start = $tier['start_range'];
                    $tier_end = $tier['end_range'];
                    $tier_price = $tier['price_per_unit'];
                    
                    // Calculate consumption within this tier
                    $tier_consumption = 0;
                    if ($tier_end === null || $tier_end > $consumption_threshold) {
                        $tier_end = $consumption_threshold;
                    }
                    
                    $tier_range = $tier_end - $tier_start;
                    $tier_consumption = min($remaining_consumption, $tier_range);
                    
                    if ($tier_consumption > 0) {
                        // Add cost for this tier
                        $consumption_amount += $tier_consumption * $tier_price;
                        $remaining_consumption -= $tier_consumption;
                    }
                }
                
                if ($consumption_amount == 0) {
                    $consumption_amount = $this->settings['minimum_payment_amount'];
                }
            }
        }
        
        // Get fixed fees from settings - now applied to all invoices
        $fixed_fees = $this->settings['fixed_fees'];
        $fixed_tva = $this->settings['unit_price'];
        
        // Return all components
        return [
            'subscriber_id' => $data['subscriber_id'],
            'consumption_id' => $consumptionId,
            'consumption' => $consumption,
            'fixed_fees' => $fixed_fees,
            'collective_entitlement_amount' => 0, // Always 0 as per new requirements
            'consumption_amount' => $consumption_amount,
            'penalties' => $consumption_amount * $fixed_tva, // Default to 0, can be modified later
            'total_amount' => $fixed_fees + $consumption_amount + $consumption_amount * $fixed_tva // Penalties will be added later if any
        ];
    }
    
    public function createInvoice($consumptionId, $dueDate = null) {
        // Calculate billing components
        $billing = $this->calculateInvoice($consumptionId);
        
        // Set due date if not provided
        if ($dueDate === null) {
            $dueDate = date('Y-m-d', strtotime('+15 days'));
            
        }
        
        // Generate invoice number
        $invoice_number = $this->generateInvoiceNumber();
        
        // Insert invoice
        $stmt = $this->db->prepare('
            INSERT INTO invoices (
                subscriber_id, consumption_id, fixed_fees, 
                collective_entitlement_amount, consumption_amount, penalties,
                total_amount, due_date, invoice_number
            ) VALUES (
                :subscriber_id, :consumption_id, :fixed_fees,
                :collective_entitlement_amount, :consumption_amount, :penalties,
                :total_amount, :due_date, :invoice_number
            )
        ');
        
        $stmt->bindValue(':subscriber_id', $billing['subscriber_id'], SQLITE3_INTEGER);
        $stmt->bindValue(':consumption_id', $billing['consumption_id'], SQLITE3_INTEGER);
        $stmt->bindValue(':fixed_fees', $billing['fixed_fees'], SQLITE3_FLOAT);
        $stmt->bindValue(':collective_entitlement_amount', $billing['collective_entitlement_amount'], SQLITE3_FLOAT);
        $stmt->bindValue(':consumption_amount', $billing['consumption_amount'], SQLITE3_FLOAT);
        $stmt->bindValue(':penalties', $billing['penalties'], SQLITE3_FLOAT);
        $stmt->bindValue(':total_amount', $billing['total_amount'], SQLITE3_FLOAT);
        $stmt->bindValue(':due_date', $dueDate);
        $stmt->bindValue(':invoice_number', $invoice_number);
        
        if (!$stmt->execute()) {
            throw new Exception('Failed to create invoice');
        }
        
        return $this->db->lastInsertRowID();
    }
    
    private function generateInvoiceNumber() {
        // Get the last invoice number
        $stmt = $this->db->query('SELECT invoice_number FROM invoices ORDER BY id DESC LIMIT 1');
        $last = $stmt->fetchArray(SQLITE3_ASSOC);
        
        if (!$last) {
            return date('Ym') . '0001';
        }
        
        $last_number = $last['invoice_number'];
        $year_month = date('Ym');
        
        if (strpos($last_number, $year_month) === 0) {
            // Same month, increment the sequence
            $sequence = intval(substr($last_number, -4)) + 1;
        } else {
            // New month, start from 1
            $sequence = 1;
        }
        
        return $year_month . str_pad($sequence, 4, '0', STR_PAD_LEFT);
    }
}
