<?php
include_once __DIR__ . '/../config/database.php';

class BankingController {
    private $db;

    public function __construct() {
        $database = new Database();
        $this->db = $database->getConnection();
    }

    private function verifyAuth($token) {
        if (!$token) return null;
        $token = str_replace('Bearer ', '', $token);
        $decoded = json_decode(base64_decode($token), true);
        if ($decoded && isset($decoded['id'])) {
            return $decoded;
        }
        return null;
    }

    private function getAuthToken() {
        $headers = apache_request_headers();
        if (isset($headers['Authorization'])) {
            return $headers['Authorization'];
        }
        return null;
    }

    public function getUserData() {
        $user = $this->verifyAuth($this->getAuthToken());
        if (!$user) {
            http_response_code(401);
            echo json_encode(["message" => "Unauthorized"]);
            return;
        }

        $userId = $user['id'];

        $stmt = $this->db->prepare("SELECT id, balance, account_number, currency, status FROM accounts WHERE user_id = ?");
        $stmt->execute([$userId]);
        $account = $stmt->fetch(PDO::FETCH_ASSOC);

        $stmt = $this->db->prepare("SELECT id, card_number, card_holder_name as card_holder, expiration_date as expiry_date, card_type as type, cvv, balance, status FROM cards WHERE user_id = ?");
        $stmt->execute([$userId]);
        $cards = $stmt->fetchAll(PDO::FETCH_ASSOC);

        $stmt = $this->db->prepare("SELECT id, transaction_id, type, amount, status, created_at, 
                                   (CASE WHEN sender_id = ? THEN 'Sent' ELSE 'Received' END) as direction 
                                   FROM transactions WHERE sender_id = ? OR receiver_id = ? ORDER BY created_at DESC LIMIT 10");
        $stmt->execute([$userId, $userId, $userId]);
        $transactions = $stmt->fetchAll(PDO::FETCH_ASSOC);

        $stmt = $this->db->prepare("SELECT u.full_name, u.username, u.email FROM users u WHERE u.id = ?");
        $stmt->execute([$userId]);
        $userInfo = $stmt->fetch(PDO::FETCH_ASSOC);

        http_response_code(200);
        echo json_encode([
            "account" => $account,
            "cards" => $cards,
            "recent_transactions" => $transactions,
            "user" => $userInfo
        ]);
    }

    public function transferMoney($data) {
        $user = $this->verifyAuth($this->getAuthToken());
        if (!$user) {
            http_response_code(401);
            echo json_encode(["message" => "Unauthorized"]);
            return;
        }

        if (empty($data->receiver_username) || empty($data->amount) || !is_numeric($data->amount) || $data->amount <= 0) {
            http_response_code(400);
            echo json_encode(["message" => "Invalid transfer details."]);
            return;
        }

        $senderId = $user['id'];
        $amount = floatval($data->amount);

        try {
            $this->db->beginTransaction();

            $stmt = $this->db->prepare("SELECT id, balance FROM accounts WHERE user_id = ? FOR UPDATE");
            $stmt->execute([$senderId]);
            $senderAccount = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$senderAccount || $senderAccount['balance'] < $amount) {
                throw new Exception("Insufficient funds.");
            }

            $stmt = $this->db->prepare("SELECT id FROM users WHERE username = ?");
            $stmt->execute([$data->receiver_username]);
            $receiverUser = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$receiverUser) {
                throw new Exception("Receiver not found.");
            }

            $receiverId = $receiverUser['id'];

            if ($senderId == $receiverId) {
                throw new Exception("Cannot send money to yourself.");
            }

            $stmt = $this->db->prepare("SELECT id, balance FROM accounts WHERE user_id = ? FOR UPDATE");
            $stmt->execute([$receiverId]);
            $receiverAccount = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$receiverAccount) {
                $accNumber = rand(1000000000, 9999999999);
                $stmt = $this->db->prepare("INSERT INTO accounts (user_id, account_number, balance) VALUES (?, ?, 0)");
                $stmt->execute([$receiverId, $accNumber]);
                $receiverAccountId = $this->db->lastInsertId();
            } else {
                $receiverAccountId = $receiverAccount['id'];
            }

            $stmt = $this->db->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?");
            $stmt->execute([$amount, $senderAccount['id']]);

            $stmt = $this->db->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?");
            $stmt->execute([$amount, $receiverAccountId]);

            $trxId = 'TRX-' . rand(100000, 999999);
            $stmt = $this->db->prepare("INSERT INTO transactions (transaction_id, sender_id, receiver_id, amount, type, status) VALUES (?, ?, ?, ?, 'Transfer', 'Completed')");
            $stmt->execute([$trxId, $senderId, $receiverId, $amount]);

            $this->db->commit();

            http_response_code(200);
            echo json_encode(["message" => "Transfer successful!"]);

        } catch (Exception $e) {
            $this->db->rollBack();
            http_response_code(400);
            echo json_encode(["message" => $e->getMessage()]);
        }
    }

    public function createCard($data) {
        $user = $this->verifyAuth($this->getAuthToken());
        if (!$user) {
            http_response_code(401);
            echo json_encode(["message" => "Unauthorized"]);
            return;
        }

        $userId = $user['id'];
        
        $stmtUser = $this->db->prepare("SELECT full_name FROM users WHERE id = ?");
        $stmtUser->execute([$userId]);
        $userData = $stmtUser->fetch(PDO::FETCH_ASSOC);
        $fullName = $userData['full_name'] ?? 'Card Holder';
        
        $cardType = (isset($data->type) && in_array($data->type, ['debit', 'credit'])) ? $data->type : 'debit';
        
        try {
            $stmt = $this->db->prepare("SELECT id FROM accounts WHERE user_id = ? LIMIT 1");
            $stmt->execute([$userId]);
            $account = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$account) {
                $accNumber = rand(1000000000, 9999999999);
                $stmt = $this->db->prepare("INSERT INTO accounts (user_id, account_number, balance) VALUES (?, ?, 0)");
                $stmt->execute([$userId, $accNumber]);
                $accountId = $this->db->lastInsertId();
            } else {
                $accountId = $account['id'];
            }
            
            $prefix = ($cardType === 'credit') ? '495000' : '487820';
            $cardNumber = $this->generateUniqueCardNumber($prefix);
            $cvv = str_pad(rand(0, 999), 3, '0', STR_PAD_LEFT);
            
            $expMonth = str_pad(date('m'), 2, '0', STR_PAD_LEFT);
            $expYear = date('y', strtotime('+3 years'));
            $expirationDate = $expMonth . '/' . $expYear;
            
            $balance = ($cardType === 'credit') ? rand(1000, 5000) : 0;
            
            $stmt = $this->db->prepare("INSERT INTO cards (user_id, account_id, card_number, card_holder_name, card_type, expiration_date, cvv, balance, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'active')");
            $stmt->execute([$userId, $accountId, $cardNumber, $fullName, $cardType, $expirationDate, $cvv, $balance]);
            
            $cardId = $this->db->lastInsertId();
            
            http_response_code(201);
            echo json_encode([
                "message" => "Card created successfully",
                "card" => [
                    "id" => $cardId,
                    "card_number" => $cardNumber,
                    "card_holder" => $fullName,
                    "type" => $cardType,
                    "expiry_date" => $expirationDate,
                    "cvv" => $cvv,
                    "balance" => $balance,
                    "status" => "active"
                ]
            ]);
        } catch (Exception $e) {
            http_response_code(500);
            echo json_encode(["message" => "Failed to create card: " . $e->getMessage()]);
        }
    }

    public function getLoans() {
        $user = $this->verifyAuth($this->getAuthToken());
        if (!$user) {
            http_response_code(401);
            echo json_encode(["message" => "Unauthorized"]);
            return;
        }

        $stmt = $this->db->prepare("SELECT * FROM loans WHERE user_id = ? ORDER BY created_at DESC");
        $stmt->execute([$user['id']]);
        $loans = $stmt->fetchAll(PDO::FETCH_ASSOC);

        http_response_code(200);
        echo json_encode($loans);
    }

    public function applyLoan($data) {
        $user = $this->verifyAuth($this->getAuthToken());
        if (!$user) {
            http_response_code(401);
            echo json_encode(["message" => "Unauthorized"]);
            return;
        }

        if (empty($data->amount) || !is_numeric($data->amount) || $data->amount <= 0) {
            http_response_code(400);
            echo json_encode(["message" => "Invalid loan amount."]);
            return;
        }

        if (empty($data->term_months) || !is_numeric($data->term_months) || $data->term_months <= 0) {
            http_response_code(400);
            echo json_encode(["message" => "Invalid term."]);
            return;
        }

        $userId = $user['id'];
        $amount = floatval($data->amount);
        $termMonths = intval($data->term_months);
        $purpose = isset($data->purpose) ? trim($data->purpose) : '';

        // Check for existing active loans
        $stmt = $this->db->prepare("SELECT COUNT(*) FROM loans WHERE user_id = ? AND status IN ('pending','active')");
        $stmt->execute([$userId]);
        $activeLoanCount = $stmt->fetchColumn();

        if ($activeLoanCount >= 3) {
            http_response_code(400);
            echo json_encode(["message" => "You already have the maximum number of active loans."]);
            return;
        }

        // Calculate loan parameters
        $interestRate = 12.0; // annual %
        $monthlyRate = $interestRate / 100 / 12;
        $monthlyPayment = $amount * ($monthlyRate * pow(1 + $monthlyRate, $termMonths)) / (pow(1 + $monthlyRate, $termMonths) - 1);
        $totalRepayment = $monthlyPayment * $termMonths;

        try {
            $this->db->beginTransaction();

            $stmt = $this->db->prepare("INSERT INTO loans (user_id, amount, interest_rate, term_months, monthly_payment, total_repayment, purpose, status) VALUES (?, ?, ?, ?, ?, ?, ?, 'active')");
            $stmt->execute([$userId, $amount, $interestRate, $termMonths, round($monthlyPayment, 2), round($totalRepayment, 2), $purpose]);

            // Credit the loan amount to user account
            $stmt = $this->db->prepare("SELECT id FROM accounts WHERE user_id = ? LIMIT 1");
            $stmt->execute([$userId]);
            $account = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$account) {
                $accNumber = rand(1000000000, 9999999999);
                $stmt = $this->db->prepare("INSERT INTO accounts (user_id, account_number, balance) VALUES (?, ?, ?)");
                $stmt->execute([$userId, $accNumber, $amount]);
            } else {
                $stmt = $this->db->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?");
                $stmt->execute([$amount, $account['id']]);
            }

            // Log as transaction
            $trxId = 'LOAN-' . rand(100000, 999999);
            $stmt = $this->db->prepare("INSERT INTO transactions (transaction_id, receiver_id, amount, type, status) VALUES (?, ?, ?, 'Loan Disbursement', 'Completed')");
            $stmt->execute([$trxId, $userId, $amount]);

            $this->db->commit();

            http_response_code(201);
            echo json_encode([
                "message" => "Loan approved and credited to your account!",
                "monthly_payment" => round($monthlyPayment, 2),
                "total_repayment" => round($totalRepayment, 2)
            ]);
        } catch (Exception $e) {
            $this->db->rollBack();
            http_response_code(500);
            echo json_encode(["message" => "Failed to process loan: " . $e->getMessage()]);
        }
    }

    public function depositMoney($data) {
        $user = $this->verifyAuth($this->getAuthToken());
        if (!$user) {
            http_response_code(401);
            echo json_encode(["message" => "Unauthorized"]);
            return;
        }

        if (empty($data->amount) || !is_numeric($data->amount) || $data->amount <= 0) {
            http_response_code(400);
            echo json_encode(["message" => "Invalid deposit amount."]);
            return;
        }

        $method = isset($data->method) && in_array($data->method, ['card', 'crypto']) ? $data->method : 'card';
        $userId = $user['id'];
        $amount = floatval($data->amount);

        try {
            $this->db->beginTransaction();

            $stmt = $this->db->prepare("SELECT id FROM accounts WHERE user_id = ? LIMIT 1");
            $stmt->execute([$userId]);
            $account = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$account) {
                $accNumber = rand(1000000000, 9999999999);
                $stmt = $this->db->prepare("INSERT INTO accounts (user_id, account_number, balance) VALUES (?, ?, ?)");
                $stmt->execute([$userId, $accNumber, $amount]);
            } else {
                $stmt = $this->db->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?");
                $stmt->execute([$amount, $account['id']]);
            }

            $cardLast4 = null;
            $cryptoCurrency = null;
            $cryptoAddress = null;

            if ($method === 'card' && isset($data->card_last4)) {
                $cardLast4 = substr($data->card_last4, -4);
            } else if ($method === 'crypto') {
                $cryptoCurrency = isset($data->crypto_currency) ? $data->crypto_currency : 'BTC';
                $cryptoAddress = isset($data->crypto_address) ? $data->crypto_address : null;
            }

            $stmt = $this->db->prepare("INSERT INTO deposits (user_id, amount, method, crypto_currency, crypto_address, card_last4, status) VALUES (?, ?, ?, ?, ?, ?, 'completed')");
            $stmt->execute([$userId, $amount, $method, $cryptoCurrency, $cryptoAddress, $cardLast4]);

            $trxId = 'DEP-' . rand(100000, 999999);
            $stmt = $this->db->prepare("INSERT INTO transactions (transaction_id, receiver_id, amount, type, status) VALUES (?, ?, ?, 'Deposit', 'Completed')");
            $stmt->execute([$trxId, $userId, $amount]);

            $this->db->commit();

            http_response_code(200);
            echo json_encode(["message" => "Deposit of $" . number_format($amount, 2) . " was successful!"]);
        } catch (Exception $e) {
            $this->db->rollBack();
            http_response_code(500);
            echo json_encode(["message" => "Deposit failed: " . $e->getMessage()]);
        }
    }
    
    private function generateUniqueCardNumber($prefix) {
        $isUnique = false;
        $cardNumber = '';
        while (!$isUnique) {
            $cardNumber = $prefix;
            while (strlen($cardNumber) < 16) {
                $cardNumber .= rand(0, 9);
            }
            $stmt = $this->db->prepare("SELECT id FROM cards WHERE card_number = ?");
            $stmt->execute([$cardNumber]);
            if ($stmt->rowCount() === 0) {
                $isUnique = true;
            }
        }
        return $cardNumber;
    }
}
?>
