<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Bill_model extends CI_Model {

    public function __construct() {
        parent::__construct();
    }

    /**
     * Get all bill categories
     */
    public function get_categories() {
        $this->db->where('is_active', 1);
        $this->db->order_by('display_order', 'ASC');
        return $this->db->get('bill_categories')->result();
    }

    /**
     * Get category by ID or slug
     */
    public function get_category($id_or_slug) {
        if (is_numeric($id_or_slug)) {
            return $this->db->get_where('bill_categories', ['id' => $id_or_slug])->row();
        }
        return $this->db->get_where('bill_categories', ['slug' => $id_or_slug])->row();
    }

    /**
     * Get providers by category
     */
    public function get_providers($category_id) {
        $this->db->where('category_id', $category_id);
        $this->db->where('is_active', 1);
        return $this->db->get('bill_providers')->result();
    }

    /**
     * Get provider by ID
     */
    public function get_provider($id) {
        return $this->db->get_where('bill_providers', ['id' => $id])->row();
    }

    /**
     * Get products/plans by provider
     */
    public function get_products($provider_id) {
        $this->db->where('provider_id', $provider_id);
        $this->db->where('is_active', 1);
        return $this->db->get('bill_products')->result();
    }

    /**
     * Get product by ID
     */
    public function get_product($id) {
        return $this->db->get_where('bill_products', ['id' => $id])->row();
    }

    /**
     * Process bill payment
     */
    public function pay_bill($data) {
        $this->load->model('Account_model');
        $this->load->model('Wallet_model');
        $this->load->model('Transaction_model');
        $this->load->model('User_model');
        
        $account = $this->Account_model->get($data['account_id']);
        if (!$account || $account->status !== 'active') {
            return ['success' => false, 'message' => 'Invalid or inactive account'];
        }
        
        $wallet = $this->Wallet_model->get_by_account($data['account_id'], $account->currency);
        if (!$wallet) {
            return ['success' => false, 'message' => 'Wallet not found'];
        }
        
        $amount = $data['amount'];
        $fee = $this->Transaction_model->calculate_fee('bill_payment', $amount);
        $total_debit = $amount + $fee;
        
        if ($wallet->available_balance < $total_debit) {
            return ['success' => false, 'message' => 'Insufficient balance'];
        }
        
        // Get category and provider
        $category = $this->get_category($data['category_id']);
        $provider = $this->get_provider($data['provider_id']);
        
        if (!$category || !$provider) {
            return ['success' => false, 'message' => 'Invalid category or provider'];
        }
        
        // Create main transaction
        $transaction_id = $this->Transaction_model->create([
            'type' => 'bill_payment',
            'category' => $category->slug,
            'source_account_id' => $data['account_id'],
            'source_wallet_id' => $wallet->id,
            'amount' => $amount,
            'fee' => $fee,
            'currency' => $account->currency,
            'narration' => $provider->name . ' - ' . $data['customer_id'],
            'status' => 'processing',
            'ip_address' => $this->input->ip_address()
        ]);
        
        if (!$transaction_id) {
            return ['success' => false, 'message' => 'Failed to create transaction'];
        }
        
        // Debit wallet
        $this->Wallet_model->debit($wallet->id, $total_debit);
        
        // Create bill payment record
        $bill_payment_id = $this->create_payment([
            'transaction_id' => $transaction_id,
            'user_id' => $data['user_id'],
            'account_id' => $data['account_id'],
            'category_id' => $data['category_id'],
            'provider_id' => $data['provider_id'],
            'product_id' => $data['product_id'] ?? null,
            'customer_id' => $data['customer_id'],
            'customer_name' => $data['customer_name'] ?? null,
            'amount' => $amount,
            'fee' => $fee,
            'status' => 'processing'
        ]);
        
        // Simulate bill provider API call
        $provider_response = $this->process_with_provider($category->slug, $provider, $data);
        
        if ($provider_response['success']) {
            // Update payment status
            $this->update_payment($bill_payment_id, [
                'status' => 'completed',
                'token' => $provider_response['token'] ?? null,
                'provider_reference' => $provider_response['reference'] ?? null
            ]);
            
            // Update transaction status
            $this->Transaction_model->update_status($transaction_id, 'completed');
            
            // Update account activity
            $this->Account_model->update_last_activity($data['account_id']);
            
            // Send email notification
            $transaction = $this->Transaction_model->get($transaction_id);
            $user = $this->User_model->get($data['user_id']);
            $updated_wallet = $this->Wallet_model->get($wallet->id);
            
            $this->load->library('mailer');
            $this->mailer->send_transaction_notification(
                $user->email,
                $user->first_name . ' ' . $user->last_name,
                [
                    'type' => 'debit',
                    'amount' => format_money($total_debit, $account->currency),
                    'account_number' => $account->account_number,
                    'new_balance' => format_money($updated_wallet->available_balance, $account->currency),
                    'narration' => 'Bill Payment: ' . $provider->name . ($fee > 0 ? ' (incl. fee ' . format_money($fee, $account->currency) . ')' : ''),
                    'reference' => $transaction->reference,
                    'date' => date('M d, Y h:i A', strtotime($transaction->created_at))
                ]
            );
            
            return [
                'success' => true,
                'message' => 'Bill payment successful',
                'transaction_id' => $transaction_id,
                'reference' => $transaction->reference,
                'token' => $provider_response['token'] ?? null
            ];
        } else {
            // Refund on failure
            $this->Wallet_model->credit($wallet->id, $total_debit);
            
            $this->update_payment($bill_payment_id, ['status' => 'failed']);
            $this->Transaction_model->update_status($transaction_id, 'failed', $provider_response['message']);
            
            return ['success' => false, 'message' => $provider_response['message']];
        }
    }

    /**
     * Process with bill provider (simulation)
     */
    private function process_with_provider($category_slug, $provider, $data) {
        // This would normally integrate with actual bill payment APIs
        // For now, we simulate a successful response
        
        // Simulate some random failures for testing
        if (mt_rand(1, 100) <= 5) { // 5% failure rate
            return ['success' => false, 'message' => 'Provider service temporarily unavailable'];
        }
        
        $response = ['success' => true, 'reference' => 'PRV' . date('YmdHis') . mt_rand(1000, 9999)];
        
        // Add token for electricity
        if ($category_slug === 'electricity') {
            $response['token'] = $this->generate_electricity_token();
        }
        
        return $response;
    }

    /**
     * Generate electricity token (simulation)
     */
    private function generate_electricity_token() {
        $segments = [];
        for ($i = 0; $i < 4; $i++) {
            $segments[] = str_pad(mt_rand(0, 9999), 4, '0', STR_PAD_LEFT);
        }
        return implode('-', $segments);
    }

    /**
     * Create bill payment record
     */
    public function create_payment($data) {
        $data['created_at'] = date('Y-m-d H:i:s');
        $this->db->insert('bill_payments', $data);
        return $this->db->insert_id();
    }

    /**
     * Update bill payment
     */
    public function update_payment($id, $data) {
        return $this->db->update('bill_payments', $data, ['id' => $id]);
    }

    /**
     * Get payment history for user
     */
    public function get_payment_history($user_id, $filters = [], $limit = 20, $offset = 0) {
        $this->db->select('bill_payments.*, bill_categories.name as category_name, bill_categories.icon,
            bill_providers.name as provider_name, transactions.reference');
        $this->db->from('bill_payments');
        $this->db->join('bill_categories', 'bill_categories.id = bill_payments.category_id');
        $this->db->join('bill_providers', 'bill_providers.id = bill_payments.provider_id');
        $this->db->join('transactions', 'transactions.id = bill_payments.transaction_id');
        $this->db->where('bill_payments.user_id', $user_id);
        
        if (!empty($filters['category_id'])) {
            $this->db->where('bill_payments.category_id', $filters['category_id']);
        }
        if (!empty($filters['status'])) {
            $this->db->where('bill_payments.status', $filters['status']);
        }
        
        $this->db->order_by('bill_payments.created_at', 'DESC');
        $this->db->limit($limit, $offset);
        
        return $this->db->get()->result();
    }

    /**
     * Save biller for quick access
     */
    public function save_biller($data) {
        // Check if already saved
        $existing = $this->db->get_where('saved_billers', [
            'user_id' => $data['user_id'],
            'provider_id' => $data['provider_id'],
            'customer_id' => $data['customer_id']
        ])->row();
        
        if ($existing) {
            return ['success' => true, 'message' => 'Biller already saved', 'id' => $existing->id];
        }
        
        $data['created_at'] = date('Y-m-d H:i:s');
        $this->db->insert('saved_billers', $data);
        
        return ['success' => true, 'message' => 'Biller saved', 'id' => $this->db->insert_id()];
    }

    /**
     * Get saved billers for user
     */
    public function get_saved_billers($user_id, $category_id = null) {
        $this->db->select('saved_billers.*, bill_categories.name as category_name, bill_providers.name as provider_name');
        $this->db->from('saved_billers');
        $this->db->join('bill_categories', 'bill_categories.id = saved_billers.category_id');
        $this->db->join('bill_providers', 'bill_providers.id = saved_billers.provider_id');
        $this->db->where('saved_billers.user_id', $user_id);
        
        if ($category_id) {
            $this->db->where('saved_billers.category_id', $category_id);
        }
        
        return $this->db->get()->result();
    }

    /**
     * Delete saved biller
     */
    public function delete_saved_biller($id, $user_id) {
        return $this->db->delete('saved_billers', ['id' => $id, 'user_id' => $user_id]);
    }

    /**
     * Buy airtime
     */
    public function buy_airtime($user_id, $account_id, $phone, $network, $amount) {
        $category = $this->get_category('airtime');
        $provider = $this->db->get_where('bill_providers', [
            'category_id' => $category->id,
            'slug' => strtolower($network)
        ])->row();
        
        if (!$provider) {
            return ['success' => false, 'message' => 'Invalid network provider'];
        }
        
        return $this->pay_bill([
            'user_id' => $user_id,
            'account_id' => $account_id,
            'category_id' => $category->id,
            'provider_id' => $provider->id,
            'customer_id' => $phone,
            'amount' => $amount
        ]);
    }

    /**
     * Buy data
     */
    public function buy_data($user_id, $account_id, $phone, $provider_id, $amount, $plan_name = '') {
        $category = $this->get_category('data');
        
        if (!$category) {
            return ['success' => false, 'message' => 'Data category not found'];
        }
        
        if ($amount <= 0) {
            return ['success' => false, 'message' => 'Invalid amount'];
        }
        
        return $this->pay_bill([
            'user_id' => $user_id,
            'account_id' => $account_id,
            'category_id' => $category->id,
            'provider_id' => $provider_id,
            'customer_id' => $phone,
            'amount' => $amount,
            'narration' => $plan_name ? "Data purchase: {$plan_name}" : 'Data purchase'
        ]);
    }
}
