<?php
// loan-details-api.php - REST API for Member Loan Management

// Load CORS configuration first
require_once __DIR__ . '/includes/cors.php';
configureCors();

// Load dependencies
require_once __DIR__ . '/includes/config_loader.php';
require_once __DIR__ . '/includes/config.php';

// Verify PDO connection exists and is valid
if (!isset($pdo) || !($pdo instanceof PDO)) {
    http_response_code(500);
    echo json_encode([
        'success' => false,
        'error' => 'Database connection not properly initialized'
    ]);
    exit();
}

// Set response headers
header('Content-Type: application/json');
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');

// Security headers
header('X-Frame-Options: DENY');
header('X-Content-Type-Options: nosniff');
header('X-XSS-Protection: 1; mode=block');
header('Referrer-Policy: strict-origin-when-cross-origin');

// Generate CSRF token for session if not exists
if (!isset($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}

// Handle preflight OPTIONS request
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit();
}

// ============================================
// AUTHENTICATION
// ============================================

// Check if user is logged in
if (!isset($_SESSION['member_id'])) {
    http_response_code(401);
    echo json_encode([
        'success' => false,
        'error' => 'Authentication required',
        'code' => 'UNAUTHORIZED'
    ]);
    exit();
}

$memberId = (int)$_SESSION['member_id'];

// ============================================
// HELPER FUNCTIONS
// ============================================

/**
 * Get member details
 */
function getMemberDetails($pdo, $memberId) {
    try {
        $stmt = $pdo->prepare("
            SELECT 
                id, 
                first_name, 
                middle_name, 
                last_name, 
                member_number,
                personal_number,
                DATE_FORMAT(created_at, '%Y-%m-%d') as join_date
            FROM members 
            WHERE id = ?
        ");
        $stmt->execute([$memberId]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    } catch (PDOException $e) {
        error_log("Error fetching member details: " . $e->getMessage());
        return null;
    }
}

/**
 * Get all loans for member
 */
function getMemberLoans($pdo, $memberId) {
    try {
        $stmt = $pdo->prepare("
            SELECT 
                l.id, 
                l.loan_number, 
                l.disbursement_amount, 
                l.repayment_amount, 
                l.recommended_period as loan_term_months,
                DATE_FORMAT(l.disbursement_date, '%Y-%m-%d') as disbursement_date,
                l.interest_rate,
                l.status,
                at.type_code,
                at.description as account_description,
                at.account_name,
                at.account_type,
                at.interest_rate as account_interest_rate
            FROM loans l
            JOIN account_types at ON l.account_type_id = at.id
            WHERE l.member_id = ? 
            ORDER BY l.disbursement_date DESC
        ");
        $stmt->execute([$memberId]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    } catch (PDOException $e) {
        error_log("Error fetching member loans: " . $e->getMessage());
        return [];
    }
}

/**
 * Get loan schedule
 */
function getLoanSchedule($pdo, $loanId) {
    try {
        $stmt = $pdo->prepare("
            SELECT 
                id as installment_number,
                DATE_FORMAT(due_date, '%Y-%m-%d') as due_date,
                principal_amount,
                interest_calculated,
                penalty_amount,
                calculated_total_due,
                principal_paid,
                interest_paid,
                penalty_paid,
                total_paid,
                status,
                DATEDIFF(CURDATE(), due_date) as days_past_due
            FROM loan_schedule
            WHERE loan_id = ?
            ORDER BY due_date
        ");
        $stmt->execute([$loanId]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    } catch (PDOException $e) {
        error_log("Error fetching loan schedule: " . $e->getMessage());
        return [];
    }
}

/**
 * Calculate loan statistics
 */
function calculateLoanStats($loans) {
    $stats = [
        'total_loans' => count($loans),
        'total_advanced' => 0,
        'total_repayment' => 0,
        'total_paid' => 0,
        'total_outstanding' => 0,
        'loans_with_balance' => 0,
        'overdue_loans' => 0,
        'paid_loans' => 0
    ];
    
    foreach ($loans as $loan) {
        $stats['total_advanced'] += $loan['disbursement_amount'];
        $stats['total_repayment'] += $loan['repayment_amount'];
        $stats['total_paid'] += $loan['totals']['paid'];
        $stats['total_outstanding'] += $loan['totals']['outstanding'];
        
        if ($loan['totals']['outstanding'] > 0) {
            $stats['loans_with_balance']++;
        }
        
        if ($loan['totals']['outstanding'] <= 0) {
            $stats['paid_loans']++;
        }
        
        // Check for overdue installments
        $hasOverdue = false;
        foreach ($loan['schedule'] as $installment) {
            if ($installment['days_past_due'] > 0 && $installment['status'] !== 'Paid') {
                $hasOverdue = true;
                break;
            }
        }
        
        if ($hasOverdue) {
            $stats['overdue_loans']++;
        }
    }
    
    $stats['performance_percentage'] = $stats['total_loans'] > 0 ? 
        ($stats['paid_loans'] / $stats['total_loans']) * 100 : 0;
    
    return $stats;
}

/**
 * Get member account statement
 */
function getAccountStatement($pdo, $memberId, $startDate, $endDate, $accountId = 'all') {
    try {
        // Get accounts
        $stmt = $pdo->prepare("
            SELECT 
                ma.id AS account_type_id, 
                ma.account_type_id, 
                ma.sub_account_code,
                at.account_name,
                at.type_code
            FROM member_accounts ma
            JOIN account_types at ON ma.account_type_id = at.id
            WHERE ma.member_id = ?
        ");
        $stmt->execute([$memberId]);
        $accounts = $stmt->fetchAll(PDO::FETCH_ASSOC);
        
        if (empty($accounts)) {
            return ['success' => false, 'error' => 'No accounts found'];
        }
        
        $statements = [];
        
        // Process each account
        foreach ($accounts as $account) {
            // Skip if not the selected account (unless 'all')
            if ($accountId !== 'all' && $account['account_type_id'] != $accountId) {
                continue;
            }
            
            // Get opening balance
            $openingBalance = getOpeningBalance($pdo, $account['account_type_id'], $startDate);
            
            // Get transactions
            $stmt = $pdo->prepare("
                SELECT 
                    t.transaction_number, 
                    t.transaction_type, 
                    t.amount, 
                    t.payment_method, 
                    t.description, 
                    t.reference_number, 
                    DATE_FORMAT(t.transaction_date, '%Y-%m-%d') as transaction_date,
                    t.created_by,
                    u.username as created_by_name
                FROM transactions t
                JOIN users u ON t.created_by = u.id
                WHERE t.member_id = ? 
                AND t.account_type_id = ?
                AND t.transaction_date BETWEEN ? AND ?
                ORDER BY t.transaction_date ASC, t.created_at ASC
            ");
            $stmt->execute([$memberId, $account['account_type_id'], $startDate, $endDate]);
            $transactions = $stmt->fetchAll(PDO::FETCH_ASSOC);
            
            // Calculate running balances
            $processed = calculateRunningBalance($transactions, $openingBalance);
            
            $statements[$account['account_name']] = [
                'account' => $account,
                'transactions' => $processed['transactions'],
                'opening_balance' => $openingBalance,
                'closing_balance' => $processed['closing_balance'],
                'summary' => calculateTransactionSummary($processed['transactions'])
            ];
        }
        
        return [
            'success' => true,
            'data' => [
                'statements' => $statements,
                'period' => [
                    'start_date' => $startDate,
                    'end_date' => $endDate
                ],
                'summary' => calculateOverallSummary($statements)
            ]
        ];
        
    } catch (PDOException $e) {
        error_log("Error fetching account statement: " . $e->getMessage());
        return ['success' => false, 'error' => 'Failed to fetch statement'];
    }
}

/**
 * Get opening balance
 */
function getOpeningBalance($pdo, $accountId, $startDate) {
    try {
        $stmt = $pdo->prepare("
            SELECT running_balance 
            FROM transactions 
            WHERE account_type_id = ? 
            AND transaction_date < ? 
            ORDER BY transaction_date DESC, created_at DESC 
            LIMIT 1
        ");
        $stmt->execute([$accountId, $startDate]);
        $openingBalance = $stmt->fetchColumn();
        
        if ($openingBalance === false) {
            $stmt = $pdo->prepare("
                SELECT opening_balance 
                FROM member_accounts 
                WHERE id = ?
            ");
            $stmt->execute([$accountId]);
            $openingBalance = $stmt->fetchColumn();
        }
        
        return $openingBalance !== false ? (float)$openingBalance : 0.00;
    } catch (PDOException $e) {
        error_log("Error fetching opening balance: " . $e->getMessage());
        return 0.00;
    }
}

/**
 * Calculate running balance
 */
function calculateRunningBalance($transactions, $openingBalance) {
    $currentBalance = $openingBalance;
    
    foreach ($transactions as &$transaction) {
        $transaction['opening_balance'] = $currentBalance;
        
        if ($transaction['transaction_type'] === 'cr') {
            $currentBalance += $transaction['amount'];
        } else {
            $currentBalance -= $transaction['amount'];
        }
        
        $transaction['running_balance'] = $currentBalance;
    }
    
    return [
        'transactions' => $transactions,
        'closing_balance' => $currentBalance
    ];
}

/**
 * Calculate transaction summary
 */
function calculateTransactionSummary($transactions) {
    $summary = [
        'total_deposits' => 0,
        'total_withdrawals' => 0,
        'total_transactions' => count($transactions),
        'average_transaction' => 0
    ];
    
    foreach ($transactions as $transaction) {
        if ($transaction['transaction_type'] === 'cr') {
            $summary['total_deposits'] += $transaction['amount'];
        } else {
            $summary['total_withdrawals'] += $transaction['amount'];
        }
    }
    
    $summary['average_transaction'] = $summary['total_transactions'] > 0 ? 
        (($summary['total_deposits'] + $summary['total_withdrawals']) / $summary['total_transactions']) : 0;
    
    return $summary;
}

/**
 * Calculate overall summary
 */
function calculateOverallSummary($statements) {
    $summary = [
        'total_accounts' => count($statements),
        'total_opening_balance' => 0,
        'total_closing_balance' => 0,
        'net_change' => 0,
        'total_deposits' => 0,
        'total_withdrawals' => 0
    ];
    
    foreach ($statements as $statement) {
        $summary['total_opening_balance'] += $statement['opening_balance'];
        $summary['total_closing_balance'] += $statement['closing_balance'];
        $summary['total_deposits'] += $statement['summary']['total_deposits'];
        $summary['total_withdrawals'] += $statement['summary']['total_withdrawals'];
    }
    
    $summary['net_change'] = $summary['total_closing_balance'] - $summary['total_opening_balance'];
    
    return $summary;
}

// ============================================
// REQUEST ROUTING
// ============================================

$method = $_SERVER['REQUEST_METHOD'];
$requestUri = $_SERVER['REQUEST_URI'];

try {
    switch ($method) {
        case 'GET':
            handleGetRequest();
            break;
            
        case 'POST':
            handlePostRequest();
            break;
            
        default:
            http_response_code(405);
            echo json_encode([
                'success' => false,
                'error' => 'Method not allowed',
                'allowed_methods' => ['GET', 'POST']
            ]);
            break;
    }
} catch (Exception $e) {
    http_response_code(500);
    echo json_encode([
        'success' => false,
        'error' => 'Internal server error',
        'message' => ENVIRONMENT === 'development' ? $e->getMessage() : 'Something went wrong'
    ]);
    error_log("Loan Details API Error: " . $e->getMessage());
}

// ============================================
// REQUEST HANDLERS
// ============================================

/**
 * Handle GET requests
 */
function handleGetRequest() {
    global $pdo, $memberId;
    
    // Check for loan ID
    if (isset($_GET['loan_id'])) {
        $loanId = (int)$_GET['loan_id'];
        
        try {
            // Verify loan belongs to member
            $stmt = $pdo->prepare("SELECT id FROM loans WHERE id = ? AND member_id = ?");
            $stmt->execute([$loanId, $memberId]);
            
            if (!$stmt->fetch()) {
                http_response_code(404);
                echo json_encode([
                    'success' => false,
                    'error' => 'Loan not found'
                ]);
                return;
            }
            
            // Get loan details
            $stmt = $pdo->prepare("
                SELECT 
                    l.*,
                    at.account_name,
                    at.account_type,
                    at.type_code,
                    at.description as account_description
                FROM loans l
                JOIN account_types at ON l.account_type_id = at.id
                WHERE l.id = ?
            ");
            $stmt->execute([$loanId]);
            $loan = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$loan) {
                http_response_code(404);
                echo json_encode([
                    'success' => false,
                    'error' => 'Loan not found'
                ]);
                return;
            }
            
            // Get schedule
            $schedule = getLoanSchedule($pdo, $loanId);
            
            // Calculate totals
            $totals = [
                'principal' => 0,
                'interest' => 0,
                'penalty' => 0,
                'due' => 0,
                'paid' => 0,
                'outstanding' => 0
            ];
            
            foreach ($schedule as $installment) {
                $totals['principal'] += $installment['principal_amount'];
                $totals['interest'] += $installment['interest_calculated'];
                $totals['penalty'] += $installment['penalty_amount'];
                $totals['due'] += $installment['calculated_total_due'];
                $totals['paid'] += $installment['total_paid'];
                $totals['outstanding'] += ($installment['calculated_total_due'] - $installment['total_paid']);
            }
            
            $loan['schedule'] = $schedule;
            $loan['totals'] = $totals;
            
            echo json_encode([
                'success' => true,
                'data' => $loan
            ]);
            
        } catch (PDOException $e) {
            http_response_code(500);
            echo json_encode([
                'success' => false,
                'error' => 'Failed to fetch loan details'
            ]);
        }
        
        return;
    }
    
    // Check for statement request
    if (isset($_GET['statement'])) {
        $startDate = $_GET['start_date'] ?? date('Y-m-01');
        $endDate = $_GET['end_date'] ?? date('Y-m-d');
        $accountId = $_GET['account_id'] ?? 'all';
        
        $statement = getAccountStatement($pdo, $memberId, $startDate, $endDate, $accountId);
        
        if ($statement['success']) {
            echo json_encode($statement);
        } else {
            http_response_code(400);
            echo json_encode($statement);
        }
        
        return;
    }
    
    // Get all loans summary
    try {
        // Get member details
        $member = getMemberDetails($pdo, $memberId);
        
        if (!$member) {
            http_response_code(404);
            echo json_encode([
                'success' => false,
                'error' => 'Member not found'
            ]);
            return;
        }
        
        // Get all loans
        $loans = getMemberLoans($pdo, $memberId);
        
        // Enhance each loan with schedule and totals
        foreach ($loans as &$loan) {
            $schedule = getLoanSchedule($pdo, $loan['id']);
            
            $totals = [
                'principal' => 0,
                'interest' => 0,
                'penalty' => 0,
                'due' => 0,
                'paid' => 0,
                'outstanding' => 0
            ];
            
            foreach ($schedule as $installment) {
                $totals['principal'] += $installment['principal_amount'];
                $totals['interest'] += $installment['interest_calculated'];
                $totals['penalty'] += $installment['penalty_amount'];
                $totals['due'] += $installment['calculated_total_due'];
                $totals['paid'] += $installment['total_paid'];
                $totals['outstanding'] += ($installment['calculated_total_due'] - $installment['total_paid']);
            }
            
            $loan['schedule'] = $schedule;
            $loan['totals'] = $totals;
            
            // Calculate progress
            $loan['progress_percentage'] = $loan['repayment_amount'] > 0 ? 
                ($loan['totals']['paid'] / $loan['repayment_amount']) * 100 : 0;
            
            // Check if overdue
            $loan['is_overdue'] = false;
            $loan['overdue_installments'] = 0;
            
            foreach ($schedule as $installment) {
                if ($installment['days_past_due'] > 0 && $installment['status'] !== 'Paid') {
                    $loan['is_overdue'] = true;
                    $loan['overdue_installments']++;
                }
            }
        }
        
        // Calculate statistics
        $stats = calculateLoanStats($loans);
        
        echo json_encode([
            'success' => true,
            'data' => [
                'member' => $member,
                'loans' => $loans,
                'stats' => $stats,
                'summary' => [
                    'total_loans' => $stats['total_loans'],
                    'total_advanced' => $stats['total_advanced'],
                    'total_outstanding' => $stats['total_outstanding'],
                    'performance_percentage' => $stats['performance_percentage']
                ]
            ]
        ], JSON_NUMERIC_CHECK);
        
    } catch (PDOException $e) {
        http_response_code(500);
        echo json_encode([
            'success' => false,
            'error' => 'Failed to fetch loan information'
        ]);
        error_log("Database error: " . $e->getMessage());
    }
}

/**
 * Handle POST requests
 */
function handlePostRequest() {
    global $pdo, $memberId;
    
    // Get JSON input
    $input = json_decode(file_get_contents('php://input'), true);
    
    if (json_last_error() !== JSON_ERROR_NONE) {
        http_response_code(400);
        echo json_encode([
            'success' => false,
            'error' => 'Invalid JSON input',
            'json_error' => json_last_error_msg()
        ]);
        return;
    }
    
    // Handle statement generation
    if (isset($input['action']) && $input['action'] === 'generate_statement') {
        // Validate required fields
        if (!isset($input['start_date']) || !isset($input['end_date'])) {
            http_response_code(400);
            echo json_encode([
                'success' => false,
                'error' => 'Missing required fields',
                'required_fields' => ['start_date', 'end_date']
            ]);
            return;
        }
        
        $startDate = $input['start_date'];
        $endDate = $input['end_date'];
        $accountId = $input['account_id'] ?? 'all';
        
        // Validate dates
        if (strtotime($startDate) > strtotime($endDate)) {
            http_response_code(400);
            echo json_encode([
                'success' => false,
                'error' => 'Start date cannot be after end date'
            ]);
            return;
        }
        
        // Get statement
        $statement = getAccountStatement($pdo, $memberId, $startDate, $endDate, $accountId);
        
        if ($statement['success']) {
            echo json_encode($statement);
        } else {
            http_response_code(400);
            echo json_encode($statement);
        }
        
        return;
    }
    
    // Handle PDF generation
    if (isset($input['action']) && $input['action'] === 'download_statement') {
        // This would generate PDF in a real implementation
        // For now, return the data for client-side PDF generation
        
        if (!isset($input['start_date']) || !isset($input['end_date'])) {
            http_response_code(400);
            echo json_encode([
                'success' => false,
                'error' => 'Missing required fields'
            ]);
            return;
        }
        
        $startDate = $input['start_date'];
        $endDate = $input['end_date'];
        $accountId = $input['account_id'] ?? 'all';
        
        // Get statement data
        $statement = getAccountStatement($pdo, $memberId, $startDate, $endDate, $accountId);
        
        if ($statement['success']) {
            // Get company settings for PDF header
            $stmt = $pdo->prepare("SELECT * FROM company_settings LIMIT 1");
            $stmt->execute();
            $companySettings = $stmt->fetch(PDO::FETCH_ASSOC);
            
            echo json_encode([
                'success' => true,
                'data' => [
                    'statement' => $statement['data'],
                    'company' => $companySettings,
                    'format' => 'pdf'
                ]
            ]);
        } else {
            http_response_code(400);
            echo json_encode($statement);
        }
        
        return;
    }
    
    // Handle CSV export
    if (isset($input['action']) && $input['action'] === 'export_csv') {
        if (!isset($input['start_date']) || !isset($input['end_date'])) {
            http_response_code(400);
            echo json_encode([
                'success' => false,
                'error' => 'Missing required fields'
            ]);
            return;
        }
        
        $startDate = $input['start_date'];
        $endDate = $input['end_date'];
        $accountId = $input['account_id'] ?? 'all';
        
        // Get statement data
        $statement = getAccountStatement($pdo, $memberId, $startDate, $endDate, $accountId);
        
        if ($statement['success']) {
            echo json_encode([
                'success' => true,
                'data' => [
                    'statement' => $statement['data'],
                    'format' => 'csv'
                ]
            ]);
        } else {
            http_response_code(400);
            echo json_encode($statement);
        }
        
        return;
    }
    
    http_response_code(400);
    echo json_encode([
        'success' => false,
        'error' => 'Invalid action'
    ]);
}
?>