<?php
/**
 * eTIMS Integration Service
 * Handles eTIMS (Electronic Tax Invoice Management System) integration
 * Kenyan Pension & Life Insurance Management System
 */

require_once __DIR__ . '/../includes/dbconn.php';

class ETIMSService {
    private $conn;
    private $baseUrl;
    private $apiKey;
    private $businessPin;
    private $branchId;
    private $mockMode;
    
    public function __construct($db_connection) {
        $this->conn = $db_connection;
        
        // Get eTIMS settings from system_settings
        $settings = $this->conn->query("SELECT setting_key, setting_value FROM system_settings 
                                       WHERE setting_key IN ('etims_base_url', 'etims_api_key', 
                                       'etims_business_pin', 'etims_branch_id', 'etims_mock_mode')")->fetch_all(MYSQLI_ASSOC);
        
        $settingsMap = [];
        foreach ($settings as $setting) {
            $settingsMap[$setting['setting_key']] = $setting['setting_value'];
        }
        
        $this->baseUrl = $settingsMap['etims_base_url'] ?? 'http://62.169.23.132:4122';
        $this->apiKey = $settingsMap['etims_api_key'] ?? '';
        $this->businessPin = $settingsMap['etims_business_pin'] ?? '';
        $this->branchId = $settingsMap['etims_branch_id'] ?? '00';
        $this->mockMode = ($settingsMap['etims_mock_mode'] ?? '0') === '1';
    }
    
    /**
     * Check eTIMS health/connectivity
     */
    public function checkHealth() {
        if ($this->mockMode) {
            return [
                'success' => true,
                'status' => 'mock',
                'message' => 'Mock mode enabled'
            ];
        }
        
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $this->baseUrl . '/health',
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 10,
            CURLOPT_SSL_VERIFYPEER => false
        ]);
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);
        
        if ($error) {
            return [
                'success' => false,
                'message' => 'Connection error: ' . $error
            ];
        }
        
        return [
            'success' => $httpCode === 200,
            'http_code' => $httpCode,
            'response' => json_decode($response, true)
        ];
    }
    
    /**
     * Generate invoice for premium payment
     */
    public function generatePremiumInvoice($premium_id) {
        $sql = "SELECT pr.*, lp.policy_number, m.member_number, m.first_name, m.last_name, 
                       m.phone_number, m.national_id, lip.product_name
                FROM premiums pr
                INNER JOIN life_policies lp ON pr.policy_id = lp.policy_id
                INNER JOIN members m ON lp.member_id = m.member_id
                LEFT JOIN life_insurance_products lip ON lp.product_id = lip.product_id
                WHERE pr.premium_id = ?";
        
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param("i", $premium_id);
        $stmt->execute();
        $premium = $stmt->get_result()->fetch_assoc();
        
        if (!$premium) {
            return ['success' => false, 'message' => 'Premium not found'];
        }
        
        // Generate invoice number
        $invoiceNumber = $this->generateInvoiceNumber();
        
        $invoiceData = [
            'businessPin' => $this->businessPin,
            'branchId' => $this->branchId,
            'invoiceNumber' => $invoiceNumber,
            'traderInvoiceNo' => 'PREMIUM-' . $premium_id,
            'customer' => [
                'name' => $premium['first_name'] . ' ' . $premium['last_name'],
                'pin' => $premium['national_id'] ?? 'A000000000A',
                'mobile' => $premium['phone_number'] ?? '',
                'address' => ''
            ],
            'items' => [
                [
                    'itemCode' => 'LIFE-PREMIUM-001',
                    'itemClassCode' => '99010000', // Insurance services
                    'itemName' => 'Life Insurance Premium - ' . ($premium['product_name'] ?? 'Policy'),
                    'quantity' => 1,
                    'price' => (float)$premium['premium_amount'],
                    'taxType' => 'B' // VAT exempt or zero-rated
                ]
            ],
            'paymentInfo' => [
                'amountPaid' => (float)$premium['premium_amount'],
                'changeGiven' => 0.00,
                'paymentModes' => [
                    [
                        'mode' => $this->getPaymentMode($premium['payment_method'] ?? 'Cash'),
                        'amount' => (float)$premium['premium_amount']
                    ]
                ]
            ],
            'remark' => 'Life Insurance Premium Payment - Policy: ' . $premium['policy_number']
        ];
        
        return $this->submitInvoice($invoiceData, $premium_id, 'PREMIUM');
    }
    
    /**
     * Generate invoice for contribution payment
     */
    public function generateContributionInvoice($contribution_id) {
        $sql = "SELECT c.*, m.member_number, m.first_name, m.last_name, 
                       m.phone_number, m.national_id, ps.scheme_name
                FROM contributions c
                INNER JOIN members m ON c.member_id = m.member_id
                LEFT JOIN pension_schemes ps ON m.scheme_id = ps.scheme_id
                WHERE c.contribution_id = ?";
        
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param("i", $contribution_id);
        $stmt->execute();
        $contribution = $stmt->get_result()->fetch_assoc();
        
        if (!$contribution) {
            return ['success' => false, 'message' => 'Contribution not found'];
        }
        
        $invoiceNumber = $this->generateInvoiceNumber();
        
        $invoiceData = [
            'businessPin' => $this->businessPin,
            'branchId' => $this->branchId,
            'invoiceNumber' => $invoiceNumber,
            'traderInvoiceNo' => 'CONT-' . $contribution_id,
            'customer' => [
                'name' => $contribution['first_name'] . ' ' . $contribution['last_name'],
                'pin' => $contribution['national_id'] ?? 'A000000000A',
                'mobile' => $contribution['phone_number'] ?? '',
                'address' => ''
            ],
            'items' => [
                [
                    'itemCode' => 'PENSION-CONT-001',
                    'itemClassCode' => '99010000',
                    'itemName' => 'Pension Contribution - ' . ($contribution['scheme_name'] ?? 'Scheme'),
                    'quantity' => 1,
                    'price' => (float)$contribution['contribution_amount'],
                    'taxType' => 'B'
                ]
            ],
            'paymentInfo' => [
                'amountPaid' => (float)$contribution['contribution_amount'],
                'changeGiven' => 0.00,
                'paymentModes' => [
                    [
                        'mode' => 'Cash',
                        'amount' => (float)$contribution['contribution_amount']
                    ]
                ]
            ],
            'remark' => 'Pension Contribution - Period: ' . $contribution['contribution_period']
        ];
        
        return $this->submitInvoice($invoiceData, $contribution_id, 'CONTRIBUTION');
    }
    
    /**
     * Generate invoice for service fee
     */
    public function generateServiceFeeInvoice($member_id, $amount, $description, $reference = null) {
        $sql = "SELECT member_number, first_name, last_name, phone_number, national_id
                FROM members WHERE member_id = ?";
        
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param("i", $member_id);
        $stmt->execute();
        $member = $stmt->get_result()->fetch_assoc();
        
        if (!$member) {
            return ['success' => false, 'message' => 'Member not found'];
        }
        
        $invoiceNumber = $this->generateInvoiceNumber();
        $traderInvoiceNo = $reference ? 'SVC-' . $reference : 'SVC-' . time();
        
        $invoiceData = [
            'businessPin' => $this->businessPin,
            'branchId' => $this->branchId,
            'invoiceNumber' => $invoiceNumber,
            'traderInvoiceNo' => $traderInvoiceNo,
            'customer' => [
                'name' => $member['first_name'] . ' ' . $member['last_name'],
                'pin' => $member['national_id'] ?? 'A000000000A',
                'mobile' => $member['phone_number'] ?? '',
                'address' => ''
            ],
            'items' => [
                [
                    'itemCode' => 'SERVICE-FEE-001',
                    'itemClassCode' => '99010000',
                    'itemName' => $description,
                    'quantity' => 1,
                    'price' => (float)$amount,
                    'taxType' => 'B'
                ]
            ],
            'paymentInfo' => [
                'amountPaid' => (float)$amount,
                'changeGiven' => 0.00,
                'paymentModes' => [
                    [
                        'mode' => 'Cash',
                        'amount' => (float)$amount
                    ]
                ]
            ],
            'remark' => 'Service Fee - ' . $description
        ];
        
        return $this->submitInvoice($invoiceData, $member_id, 'SERVICE_FEE', $reference);
    }
    
    /**
     * Submit invoice to eTIMS
     */
    private function submitInvoice($invoiceData, $sourceId, $sourceType, $reference = null) {
        if ($this->mockMode) {
            // Mock response for development
            return [
                'success' => true,
                'mock' => true,
                'invoice_number' => $invoiceData['invoiceNumber'],
                'receipt_signature' => 'MOCK-' . bin2hex(random_bytes(16)),
                'message' => 'Mock mode: Invoice generated successfully'
            ];
        }
        
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $this->baseUrl . '/api/invoice/process',
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => json_encode($invoiceData),
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                'X-API-Key: ' . $this->apiKey
            ],
            CURLOPT_TIMEOUT => 30,
            CURLOPT_SSL_VERIFYPEER => false
        ]);
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);
        
        if ($error) {
            return [
                'success' => false,
                'message' => 'eTIMS connection error: ' . $error
            ];
        }
        
        $result = json_decode($response, true);
        
        if ($httpCode === 200 && isset($result['data'])) {
            // Save invoice record
            $this->saveInvoiceRecord($sourceId, $sourceType, $invoiceData['invoiceNumber'], $result['data'], $reference);
            
            return [
                'success' => true,
                'invoice_number' => $result['data']['invoiceNumber'] ?? $invoiceData['invoiceNumber'],
                'receipt_signature' => $result['data']['receiptSignature'] ?? null,
                'cu_serial' => $result['data']['cuSerial'] ?? null,
                'data' => $result['data']
            ];
        }
        
        return [
            'success' => false,
            'http_code' => $httpCode,
            'message' => $result['message'] ?? 'Failed to submit invoice',
            'response' => $result
        ];
    }
    
    /**
     * Generate credit note
     */
    public function generateCreditNote($originalInvoiceNumber, $reason, $items, $customer) {
        if ($this->mockMode) {
            return [
                'success' => true,
                'mock' => true,
                'credit_note_number' => rand(5000, 9999),
                'message' => 'Mock mode: Credit note generated'
            ];
        }
        
        $creditNoteNumber = $this->generateInvoiceNumber();
        
        $creditNoteData = [
            'businessPin' => $this->businessPin,
            'branchId' => $this->branchId,
            'originalInvoiceNumber' => $originalInvoiceNumber,
            'creditNoteNumber' => $creditNoteNumber,
            'traderInvoiceNo' => 'CN-' . $creditNoteNumber,
            'customer' => $customer,
            'items' => $items,
            'reason' => $reason
        ];
        
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $this->baseUrl . '/api/credit-note/process',
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => json_encode($creditNoteData),
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                'X-API-Key: ' . $this->apiKey
            ],
            CURLOPT_TIMEOUT => 30,
            CURLOPT_SSL_VERIFYPEER => false
        ]);
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);
        
        if ($error) {
            return [
                'success' => false,
                'message' => 'eTIMS connection error: ' . $error
            ];
        }
        
        $result = json_decode($response, true);
        
        if ($httpCode === 200) {
            return [
                'success' => true,
                'credit_note_number' => $creditNoteNumber,
                'data' => $result
            ];
        }
        
        return [
            'success' => false,
            'http_code' => $httpCode,
            'message' => $result['message'] ?? 'Failed to submit credit note',
            'response' => $result
        ];
    }
    
    /**
     * Register items in eTIMS
     */
    public function registerItems($items) {
        if ($this->mockMode) {
            return [
                'success' => true,
                'mock' => true,
                'message' => 'Mock mode: Items registered'
            ];
        }
        
        $data = [
            'businessPin' => $this->businessPin,
            'branchId' => $this->branchId,
            'Items' => count($items),
            'ItemsList' => $items
        ];
        
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $this->baseUrl . '/api/items/register-json',
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => json_encode($data),
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                'X-API-Key: ' . $this->apiKey
            ],
            CURLOPT_TIMEOUT => 30,
            CURLOPT_SSL_VERIFYPEER => false
        ]);
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);
        
        if ($error) {
            return [
                'success' => false,
                'message' => 'eTIMS connection error: ' . $error
            ];
        }
        
        $result = json_decode($response, true);
        
        return [
            'success' => $httpCode === 200,
            'http_code' => $httpCode,
            'data' => $result
        ];
    }
    
    /**
     * Generate unique invoice number
     */
    private function generateInvoiceNumber() {
        // Get last invoice number from database
        $sql = "SELECT MAX(CAST(invoice_number AS UNSIGNED)) as last_number 
                FROM etims_invoices 
                WHERE invoice_number REGEXP '^[0-9]+$'";
        $result = $this->conn->query($sql);
        $row = $result->fetch_assoc();
        $lastNumber = $row['last_number'] ?? 5000;
        
        return $lastNumber + 1;
    }
    
    /**
     * Get payment mode for eTIMS
     */
    private function getPaymentMode($paymentMethod) {
        $modes = [
            'CASH' => 'Cash',
            'MPESA' => 'M-Pesa',
            'BANK_TRANSFER' => 'Bank Transfer',
            'CHEQUE' => 'Cheque',
            'CARD' => 'Card'
        ];
        
        return $modes[strtoupper($paymentMethod)] ?? 'Cash';
    }
    
    /**
     * Save invoice record to database
     */
    private function saveInvoiceRecord($sourceId, $sourceType, $invoiceNumber, $etimsData, $reference = null) {
        $sql = "INSERT INTO etims_invoices (
                   source_id, source_type, invoice_number, trader_invoice_no,
                   receipt_signature, cu_serial, etims_response, reference,
                   created_at
               ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW())";
        
        $traderInvoiceNo = $etimsData['traderInvoiceNo'] ?? null;
        $receiptSignature = $etimsData['receiptSignature'] ?? null;
        $cuSerial = $etimsData['cuSerial'] ?? null;
        $etimsResponse = json_encode($etimsData);
        
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param("isisssss", $sourceId, $sourceType, $invoiceNumber, 
                         $traderInvoiceNo, $receiptSignature, $cuSerial, 
                         $etimsResponse, $reference);
        $stmt->execute();
    }
    
    /**
     * Get invoice by source
     */
    public function getInvoice($sourceId, $sourceType) {
        $sql = "SELECT * FROM etims_invoices 
                WHERE source_id = ? AND source_type = ? 
                ORDER BY created_at DESC LIMIT 1";
        
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param("is", $sourceId, $sourceType);
        $stmt->execute();
        
        return $stmt->get_result()->fetch_assoc();
    }
}
