<?php
/**
 * Life Insurance Service
 * Handles all life insurance-related operations
 * Kenyan Pension & Life Insurance Management System
 * 
 * @package Classes
 * @author Senior Fintech Engineer
 */

class LifeInsuranceService {
    private $conn;
    
    /**
     * Constructor
     * 
     * @param mysqli $conn Database connection
     */
    public function __construct($conn) {
        $this->conn = $conn;
    }
    
    /**
     * Create a new life insurance policy
     * 
     * @param array $policyData Policy data
     * @return array Result with policy_id or error
     */
    public function createPolicy($policyData) {
        try {
            // Validate required fields
            $required = ['product_id', 'policy_number', 'sum_assured', 'premium_amount', 'policy_start_date'];
            foreach ($required as $field) {
                if (empty($policyData[$field])) {
                    return ['success' => false, 'message' => "Field {$field} is required"];
                }
            }
            
            // Start transaction
            $this->conn->begin_transaction();
            
            // Insert policy
            $sql = "INSERT INTO life_policies (
                policy_number, product_id, member_id, sum_assured, premium_amount,
                premium_frequency, policy_start_date, policy_end_date, maturity_date,
                policy_status
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'ACTIVE')";
            
            $stmt = $this->conn->prepare($sql);
            $stmt->bind_param(
                "siiddssss",
                $policyData['policy_number'],
                $policyData['product_id'],
                $policyData['member_id'] ?? null,
                $policyData['sum_assured'],
                $policyData['premium_amount'],
                $policyData['premium_frequency'] ?? 'ANNUAL',
                $policyData['policy_start_date'],
                $policyData['policy_end_date'] ?? null,
                $policyData['maturity_date'] ?? null
            );
            
            if (!$stmt->execute()) {
                throw new Exception("Failed to create policy: " . $stmt->error);
            }
            
            $policy_id = $this->conn->insert_id;
            
            // Commit transaction
            $this->conn->commit();
            
            // Log activity
            $this->logActivity($policy_id, 'POLICY_CREATED', 'LIFE_INSURANCE', $policy_id, null, $policyData);
            
            return [
                'success' => true,
                'message' => 'Policy created successfully',
                'policy_id' => $policy_id
            ];
            
        } catch (Exception $e) {
            $this->conn->rollback();
            error_log("LifeInsuranceService::createPolicy Error: " . $e->getMessage());
            return [
                'success' => false,
                'message' => 'Failed to create policy: ' . $e->getMessage()
            ];
        }
    }
    
    /**
     * Get policy by ID
     * 
     * @param int $policy_id Policy ID
     * @return array|null Policy data or null
     */
    public function getPolicy($policy_id) {
        $sql = "SELECT lp.*, lip.product_name, lip.product_type, m.member_number, m.first_name, m.last_name
                FROM life_policies lp
                LEFT JOIN life_insurance_products lip ON lp.product_id = lip.product_id
                LEFT JOIN members m ON lp.member_id = m.member_id
                WHERE lp.policy_id = ?";
        
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param("i", $policy_id);
        $stmt->execute();
        $result = $stmt->get_result();
        
        return $result->fetch_assoc();
    }
    
    /**
     * Get policies with filters
     * 
     * @param array $filters Search filters
     * @param int $page Page number
     * @param int $perPage Records per page
     * @return array Policies list and pagination
     */
    public function getPolicies($filters = [], $page = 1, $perPage = 20) {
        $offset = ($page - 1) * $perPage;
        
        $where = ["1=1"];
        $params = [];
        $types = '';
        
        if (!empty($filters['product_id'])) {
            $where[] = "lp.product_id = ?";
            $params[] = $filters['product_id'];
            $types .= 'i';
        }
        
        if (!empty($filters['status'])) {
            $where[] = "lp.policy_status = ?";
            $params[] = $filters['status'];
            $types .= 's';
        }
        
        if (!empty($filters['search'])) {
            $where[] = "(lp.policy_number LIKE ? OR m.member_number LIKE ?)";
            $searchTerm = '%' . $filters['search'] . '%';
            $params[] = $searchTerm;
            $params[] = $searchTerm;
            $types .= 'ss';
        }
        
        $whereClause = implode(' AND ', $where);
        
        // Get total count
        $countSql = "SELECT COUNT(*) as total FROM life_policies lp
                     LEFT JOIN members m ON lp.member_id = m.member_id
                     WHERE $whereClause";
        $countStmt = $this->conn->prepare($countSql);
        if (!empty($params)) {
            $countStmt->bind_param($types, ...$params);
        }
        $countStmt->execute();
        $total = $countStmt->get_result()->fetch_assoc()['total'];
        
        // Get policies
        $sql = "SELECT lp.*, lip.product_name, lip.product_type, m.member_number, m.first_name, m.last_name
                FROM life_policies lp
                LEFT JOIN life_insurance_products lip ON lp.product_id = lip.product_id
                LEFT JOIN members m ON lp.member_id = m.member_id
                WHERE $whereClause
                ORDER BY lp.created_at DESC
                LIMIT ? OFFSET ?";
        
        $params[] = $perPage;
        $params[] = $offset;
        $types .= 'ii';
        
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param($types, ...$params);
        $stmt->execute();
        $result = $stmt->get_result();
        
        $policies = [];
        while ($row = $result->fetch_assoc()) {
            $policies[] = $row;
        }
        
        return [
            'policies' => $policies,
            'pagination' => [
                'page' => $page,
                'per_page' => $perPage,
                'total' => $total,
                'total_pages' => ceil($total / $perPage)
            ]
        ];
    }
    
    /**
     * Calculate surrender value
     * 
     * @param int $policy_id Policy ID
     * @return array Result with surrender value
     */
    public function calculateSurrenderValue($policy_id) {
        try {
            // Call stored procedure
            $sql = "CALL sp_calculate_surrender_value(?, CURDATE(), @surrender_value, @is_eligible, @eligibility_reason)";
            $stmt = $this->conn->prepare($sql);
            $stmt->bind_param("i", $policy_id);
            $stmt->execute();
            $stmt->close();
            
            // Get results
            $result = $this->conn->query("SELECT @surrender_value as surrender_value, @is_eligible as is_eligible, @eligibility_reason as eligibility_reason");
            $data = $result->fetch_assoc();
            
            return [
                'success' => true,
                'surrender_value' => $data['surrender_value'] ?? 0,
                'is_eligible' => $data['is_eligible'] ?? false,
                'eligibility_reason' => $data['eligibility_reason'] ?? null
            ];
        } catch (Exception $e) {
            error_log("LifeInsuranceService::calculateSurrenderValue Error: " . $e->getMessage());
            return [
                'success' => false,
                'message' => 'Failed to calculate surrender value: ' . $e->getMessage()
            ];
        }
    }
    
    /**
     * Calculate claim amount
     * 
     * @param int $policy_id Policy ID
     * @param string $claim_type Claim type
     * @return array Result with claim amount
     */
    public function calculateClaimAmount($policy_id, $claim_type) {
        try {
            // Call stored procedure
            $sql = "CALL sp_calculate_life_claim_amount(?, ?, @claim_amount, @sum_assured_component, @bonus_component)";
            $stmt = $this->conn->prepare($sql);
            $stmt->bind_param("is", $policy_id, $claim_type);
            $stmt->execute();
            $stmt->close();
            
            // Get results
            $result = $this->conn->query("SELECT @claim_amount as claim_amount, @sum_assured_component as sum_assured_component, @bonus_component as bonus_component");
            $data = $result->fetch_assoc();
            
            return [
                'success' => true,
                'claim_amount' => $data['claim_amount'] ?? 0,
                'sum_assured_component' => $data['sum_assured_component'] ?? 0,
                'bonus_component' => $data['bonus_component'] ?? 0
            ];
        } catch (Exception $e) {
            error_log("LifeInsuranceService::calculateClaimAmount Error: " . $e->getMessage());
            return [
                'success' => false,
                'message' => 'Failed to calculate claim amount: ' . $e->getMessage()
            ];
        }
    }
    
    /**
     * Log activity
     */
    private function logActivity($entity_id, $event_type, $event_category, $policy_id, $old_value, $new_value) {
        $sql = "INSERT INTO audit_logs (
            event_type, event_category, policy_id, event_description,
            old_value, new_value, performed_by, ip_address, created_at
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)";
        
        $stmt = $this->conn->prepare($sql);
        $event_description = "Life insurance operation: $event_type";
        $performed_by = $_SESSION['username'] ?? 'SYSTEM';
        $ip_address = $_SERVER['REMOTE_ADDR'] ?? null;
        
        $old_json = $old_value ? json_encode($old_value) : null;
        $new_json = $new_value ? json_encode($new_value) : null;
        
        $stmt->bind_param("ssisssss", 
            $event_type, $event_category, $policy_id, $event_description,
            $old_json, $new_json, $performed_by, $ip_address
        );
        
        $stmt->execute();
    }
}
