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

class Transfers extends Auth_Controller {

    public function __construct() {
        parent::__construct();
        $this->load->model('Account_model');
        $this->load->model('Wallet_model');
        $this->load->model('Transaction_model');
    }

    /**
     * Transfer page
     */
    public function index() {
        $accounts = $this->Account_model->get_by_user($this->user->id);
        
        // Get beneficiaries
        $beneficiaries = $this->db->get_where('beneficiaries', ['user_id' => $this->user->id])->result();
        
        $this->data['title'] = 'Transfer Money';
        $this->data['accounts'] = $accounts;
        $this->data['beneficiaries'] = $beneficiaries;
        
        $this->render('transfers/index', $this->data);
    }

    /**
     * Internal transfer (within the bank)
     */
    public function internal() {
        if ($this->input->method() === 'get') {
            $accounts = $this->Account_model->get_by_user($this->user->id);
            
            // Get pre-filled destination account from query parameter
            $to_account = $this->input->get('to', TRUE);
            
            $this->data['title'] = 'Internal Transfer';
            $this->data['accounts'] = $accounts;
            $this->data['to_account'] = $to_account;
            
            $this->render('transfers/internal', $this->data);
            return;
        }
        
        $this->form_validation->set_rules('source_account', 'Source Account', 'required');
        $this->form_validation->set_rules('destination_account', 'Destination Account', 'required');
        $this->form_validation->set_rules('amount', 'Amount', 'required|numeric|greater_than[0]');
        
        if (!$this->form_validation->run()) {
            if ($this->input->is_ajax_request()) {
                $this->error('Validation failed', validation_errors());
                return;
            }
            $this->session->set_flashdata('error', validation_errors());
            redirect('transfers/internal');
            return;
        }
        
        // Verify OTP for non-admin users
        if (!$this->is_admin()) {
            $otp_verified = $this->session->userdata('otp_verified_transfer');
            if (!$otp_verified || (time() - $otp_verified) > 300) {
                // OTP not verified or expired
                $message = 'Please verify your identity with OTP';
                if ($this->input->is_ajax_request()) {
                    $this->error($message, ['require_otp' => true]);
                    return;
                }
                $this->session->set_flashdata('error', $message);
                redirect('transfers/internal');
                return;
            }
            // Clear OTP verification after use
            $this->session->unset_userdata('otp_verified_transfer');
        }
        
        $source_account_id = $this->input->post('source_account');
        $dest_account_number = $this->input->post('destination_account');
        $amount = floatval($this->input->post('amount'));
        $narration = $this->input->post('narration', TRUE) ?: 'Transfer';
        
        // Verify source account belongs to user
        $source_account = $this->Account_model->get($source_account_id);
        if (!$source_account || $source_account->user_id != $this->user->id) {
            $message = 'Invalid source account';
            if ($this->input->is_ajax_request()) {
                $this->error($message);
                return;
            }
            $this->session->set_flashdata('error', $message);
            redirect('transfers/internal');
            return;
        }
        
        // Find destination account
        $dest_account = $this->Account_model->get_by_account_number($dest_account_number);
        if (!$dest_account) {
            $message = 'Destination account not found';
            if ($this->input->is_ajax_request()) {
                $this->error($message);
                return;
            }
            $this->session->set_flashdata('error', $message);
            redirect('transfers/internal');
            return;
        }
        
        // Cannot transfer to same account (except for admin users)
        if (!$this->is_admin() && $source_account->id == $dest_account->id) {
            $message = 'Cannot transfer to the same account';
            if ($this->input->is_ajax_request()) {
                $this->error($message);
                return;
            }
            $this->session->set_flashdata('error', $message);
            redirect('transfers/internal');
            return;
        }
        
        // Process transfer
        $result = $this->Transaction_model->process_internal_transfer(
            $source_account->id,
            $dest_account->id,
            $amount,
            $narration,
            $this->user->id
        );
        
        if ($result['success']) {
            // Get transaction details
            $transaction = $this->Transaction_model->get($result['transaction_id']);
            
            // Get updated wallet balances
            $source_wallet = $this->Wallet_model->get_by_account($source_account->id, $source_account->currency);
            $dest_wallet = $this->Wallet_model->get_by_account($dest_account->id, $dest_account->currency);
            
            // Send in-app notifications
            $this->Notification_model->send_transaction_notification(
                $source_account->user_id, 'debit', $amount, $result['reference'], $narration
            );
            
            $this->Notification_model->send_transaction_notification(
                $dest_account->user_id, 'credit', $amount, $result['reference'], $narration
            );
            
            // Send email notifications
            $this->load->library('mailer');
            
            // Notify sender (debit)
            $sender = $this->User_model->get($source_account->user_id);
            $this->mailer->send_transaction_notification(
                $sender->email,
                $sender->first_name . ' ' . $sender->last_name,
                [
                    'type' => 'debit',
                    'amount' => format_money($amount, $source_account->currency),
                    'account_number' => $source_account->account_number,
                    'new_balance' => format_money($source_wallet->available_balance, $source_account->currency),
                    'narration' => $narration . ' to ' . $dest_account->account_number,
                    'reference' => $transaction->reference,
                    'date' => date('M d, Y h:i A', strtotime($transaction->created_at))
                ]
            );
            
            // Notify receiver (credit)
            $receiver = $this->User_model->get($dest_account->user_id);
            $this->mailer->send_transaction_notification(
                $receiver->email,
                $receiver->first_name . ' ' . $receiver->last_name,
                [
                    'type' => 'credit',
                    'amount' => format_money($amount, $dest_account->currency),
                    'account_number' => $dest_account->account_number,
                    'new_balance' => format_money($dest_wallet->available_balance, $dest_account->currency),
                    'narration' => $narration . ' from ' . $source_account->account_number,
                    'reference' => $transaction->reference,
                    'date' => date('M d, Y h:i A', strtotime($transaction->created_at))
                ]
            );
            
            if ($this->input->is_ajax_request()) {
                $this->success($result['message'], ['reference' => $result['reference']]);
                return;
            }
            
            $this->session->set_flashdata('success', $result['message'] . ' Reference: ' . $result['reference']);
            redirect('transactions/view/' . $result['transaction_id']);
        } else {
            if ($this->input->is_ajax_request()) {
                $this->error($result['message']);
                return;
            }
            $this->session->set_flashdata('error', $result['message']);
            redirect('transfers/internal');
        }
    }

    /**
     * Bank transfer (external - other banks). After OTP, creates transaction with status pending.
     */
    public function external() {
        if ($this->input->method() === 'get') {
            $accounts = $this->Account_model->get_by_user($this->user->id);
            $beneficiaries = $this->db->get_where('beneficiaries', ['user_id' => $this->user->id, 'beneficiary_type' => 'external'])->result();
            $to_account = $this->input->get('to', TRUE);
            $to_bank = $this->input->get('bank_code', TRUE);
            $to_name = $this->input->get('name', TRUE);
            $this->data['title'] = 'Bank Transfer';
            $this->data['accounts'] = $accounts;
            $this->data['beneficiaries'] = $beneficiaries;
            $this->data['to_account'] = $to_account;
            $this->data['to_bank_code'] = $to_bank;
            $this->data['to_name'] = $to_name;
            $this->render('transfers/external', $this->data);
            return;
        }

        $this->form_validation->set_rules('source_account', 'Source Account', 'required');
        $this->form_validation->set_rules('amount', 'Amount', 'required|numeric|greater_than[0]');
        $this->form_validation->set_rules('recipient_name', 'Recipient Name', 'required');
        $this->form_validation->set_rules('recipient_account', 'Recipient Account', 'required');
        $this->form_validation->set_rules('bank_code', 'Bank', 'required');
        $this->form_validation->set_rules('bank_name', 'Bank Name', 'required');

        if (!$this->form_validation->run()) {
            $this->session->set_flashdata('error', validation_errors());
            redirect('transfers/external');
            return;
        }

        if (!$this->is_admin()) {
            $otp_verified = $this->session->userdata('otp_verified_bank_transfer');
            if (!$otp_verified || (time() - $otp_verified) > 300) {
                $this->session->set_flashdata('error', 'Please verify your identity with OTP');
                redirect('transfers/external');
                return;
            }
            $this->session->unset_userdata('otp_verified_bank_transfer');
        }

        $source_account_id = (int) $this->input->post('source_account');
        $source_account = $this->Account_model->get($source_account_id);
        if (!$source_account || $source_account->user_id != $this->user->id) {
            $this->session->set_flashdata('error', 'Invalid source account');
            redirect('transfers/external');
            return;
        }

        $amount = floatval($this->input->post('amount'));
        $narration = $this->input->post('narration', TRUE) ?: 'Bank transfer';
        $recipient_name = $this->input->post('recipient_name', TRUE);
        $recipient_account = $this->input->post('recipient_account', TRUE);
        $bank_code = $this->input->post('bank_code', TRUE);
        $bank_name = $this->input->post('bank_name', TRUE);

        $result = $this->Transaction_model->create_pending_external_transfer(
            $source_account_id, $amount, $narration,
            $recipient_name, $recipient_account, $bank_code, $bank_name,
            $this->user->id
        );

        if ($result['success']) {
            $this->session->set_flashdata('success', $result['message'] . ' Reference: ' . $result['reference']);
            redirect('transactions/view/' . $result['transaction_id']);
        } else {
            $this->session->set_flashdata('error', $result['message']);
            redirect('transfers/external');
        }
    }

    /**
     * International transfer. After OTP, creates transaction with status pending.
     */
    public function international() {
        if ($this->input->method() === 'get') {
            $accounts = $this->Account_model->get_by_user($this->user->id);
            $beneficiaries = $this->db->get_where('beneficiaries', ['user_id' => $this->user->id, 'beneficiary_type' => 'international'])->result();
            $this->data['title'] = 'International Transfer';
            $this->data['accounts'] = $accounts;
            $this->data['beneficiaries'] = $beneficiaries;
            $this->data['to_account'] = $this->input->get('to', TRUE);
            $this->data['to_swift'] = $this->input->get('swift', TRUE);
            $this->data['to_name'] = $this->input->get('name', TRUE);
            $this->data['to_country'] = $this->input->get('country', TRUE);
            $this->data['to_currency'] = $this->input->get('currency', TRUE);
            $this->render('transfers/international', $this->data);
            return;
        }

        $this->form_validation->set_rules('source_account', 'Source Account', 'required');
        $this->form_validation->set_rules('amount', 'Amount', 'required|numeric|greater_than[0]');
        $this->form_validation->set_rules('recipient_name', 'Recipient Name', 'required');
        $this->form_validation->set_rules('recipient_account', 'Recipient Account / IBAN', 'required');
        $this->form_validation->set_rules('recipient_bank_swift', 'Bank SWIFT/BIC', 'required');
        $this->form_validation->set_rules('recipient_country', 'Country', 'required');
        $this->form_validation->set_rules('recipient_currency', 'Currency', 'required');

        if (!$this->form_validation->run()) {
            $this->session->set_flashdata('error', validation_errors());
            redirect('transfers/international');
            return;
        }

        if (!$this->is_admin()) {
            $otp_verified = $this->session->userdata('otp_verified_international_transfer');
            if (!$otp_verified || (time() - $otp_verified) > 300) {
                $this->session->set_flashdata('error', 'Please verify your identity with OTP');
                redirect('transfers/international');
                return;
            }
            $this->session->unset_userdata('otp_verified_international_transfer');
        }

        $source_account_id = (int) $this->input->post('source_account');
        $source_account = $this->Account_model->get($source_account_id);
        if (!$source_account || $source_account->user_id != $this->user->id) {
            $this->session->set_flashdata('error', 'Invalid source account');
            redirect('transfers/international');
            return;
        }

        $amount = floatval($this->input->post('amount'));
        $narration = $this->input->post('narration', TRUE) ?: 'International transfer';
        $recipient_name = $this->input->post('recipient_name', TRUE);
        $recipient_account = $this->input->post('recipient_account', TRUE);
        $recipient_bank_swift = $this->input->post('recipient_bank_swift', TRUE);
        $recipient_country = $this->input->post('recipient_country', TRUE);
        $recipient_currency = $this->input->post('recipient_currency', TRUE);
        $exchange_rate = floatval($this->input->post('exchange_rate')) ?: 1;

        $result = $this->Transaction_model->create_pending_international_transfer(
            $source_account_id, $amount, $narration,
            $recipient_name, $recipient_account, $recipient_bank_swift, $recipient_country, $recipient_currency, $exchange_rate,
            $this->user->id
        );

        if ($result['success']) {
            $this->session->set_flashdata('success', $result['message'] . ' Reference: ' . $result['reference']);
            redirect('transactions/view/' . $result['transaction_id']);
        } else {
            $this->session->set_flashdata('error', $result['message']);
            redirect('transfers/international');
        }
    }

    /**
     * Lookup account by number
     */
    public function lookup_account() {
        $account_number = $this->input->post('account_number', TRUE);
        
        $account = $this->Account_model->get_by_account_number($account_number);
        
        if (!$account) {
            $this->error('Account not found');
            return;
        }
        
        // Get account holder name
        $user = $this->User_model->get($account->user_id);
        
        $this->success('Account found', [
            'account_name' => $account->account_name,
            'account_holder' => $user->first_name . ' ' . $user->last_name,
            'account_type' => $account->account_type
        ]);
    }

    /**
     * Add beneficiary
     */
    public function add_beneficiary() {
        $this->form_validation->set_rules('name', 'Name', 'required');
        $this->form_validation->set_rules('account_number', 'Account Number', 'required');
        
        if (!$this->form_validation->run()) {
            $this->error('Validation failed', validation_errors());
            return;
        }
        
        $type = $this->input->post('beneficiary_type', TRUE) ?: 'internal';
        $bank_code = $type === 'international' ? $this->input->post('swift_code', TRUE) : $this->input->post('bank_code', TRUE);
        $bank_name = $type === 'international' ? $this->input->post('country_name', TRUE) : $this->input->post('bank_name', TRUE);
        $data = [
            'user_id' => $this->user->id,
            'name' => $this->input->post('name', TRUE),
            'account_number' => $this->input->post('account_number', TRUE),
            'bank_code' => $bank_code,
            'bank_name' => $bank_name,
            'beneficiary_type' => $type,
            'currency' => $this->input->post('currency', TRUE) ?: 'USD',
            'created_at' => date('Y-m-d H:i:s')
        ];
        
        $this->db->insert('beneficiaries', $data);
        
        $this->success('Beneficiary added successfully', ['id' => $this->db->insert_id()]);
    }

    /**
     * Delete beneficiary
     */
    public function delete_beneficiary($id) {
        $this->db->delete('beneficiaries', ['id' => $id, 'user_id' => $this->user->id]);
        
        if ($this->db->affected_rows() > 0) {
            $this->success('Beneficiary deleted');
        } else {
            $this->error('Beneficiary not found');
        }
    }

    /**
     * Get beneficiaries
     */
    public function beneficiaries() {
        $beneficiaries = $this->db->get_where('beneficiaries', ['user_id' => $this->user->id])->result();
        
        if ($this->input->is_ajax_request()) {
            $this->success('Beneficiaries retrieved', $beneficiaries);
            return;
        }
        
        $this->data['title'] = 'Beneficiaries';
        $this->data['beneficiaries'] = $beneficiaries;
        
        $this->render('transfers/beneficiaries', $this->data);
    }
}
