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

class Withdraw extends Member_Controller
{
	// 1000 coins = $1.00  (i.e. 1 coin = $0.001)
	// This overrides whatever $settings['currency_rate'] holds elsewhere on
	// the site, so this page's math is always correct without depending on
	// a global admin setting. To change the rate, just edit this number —
	// e.g. for "100 coins = $1" use 0.01, for "10000 coins = $1" use 0.0001.
	const COIN_TO_USD_RATE = 0.001;

	// Small tolerance for float rounding when comparing a submitted amount
	// to a fixed package's exact required cost.
	const FIXED_AMOUNT_EPSILON = 0.0000001;

	public function __construct()
	{
		parent::__construct();
		$this->load->model(['m_withdraw', 'm_hidden']);
		$this->load->library('form_validation');
		// Manual methods list lives in application/config/withdraw_methods.php
		// Edit that file directly to add/remove/disable a method — no admin UI needed.
		// NOTE: this file just does `return [...]`, so it's read with a plain
		// include() rather than $this->load->config() (CI's config loader
		// requires a $config[...] assignment, which throws "does not appear
		// to contain a valid configuration array" for a bare return array).
	}

	/**
	 * Reads application/config/withdraw_methods.php fresh each call.
	 */
	private function load_methods()
	{
		$path = APPPATH . 'config/withdraw_methods.php';
		if (!file_exists($path)) {
			log_message('error', 'withdraw_methods.php config file is missing at ' . $path);
			return [];
		}
		$methods = include $path;
		if (!is_array($methods)) {
			log_message('error', 'withdraw_methods.php did not return an array.');
			return [];
		}
		return $methods;
	}

	/**
	 * Returns every active method, grouped by category (games / crypto / cash)
	 * and then sub-grouped (e.g. 'freefire', 'pubg', 'visa', 'paypal'). Methods
	 * with no 'group' set (e.g. plain crypto coins) are bucketed under '_none'
	 * and the view renders those as direct cards instead of a group tile.
	 *
	 * Returns:
	 *   [
	 *     'methods' => ['games' => ['freefire' => [id => method, ...], '_none' => [...]], ...],
	 *     'groups'  => ['games' => ['freefire' => ['label' => ..., 'image' => ...]], ...],
	 *   ]
	 */
	private function get_active_methods()
	{
		$methods = $this->load_methods();

		$grouped = ['games' => [], 'crypto' => [], 'cash' => []];
		$groupsMeta = ['games' => [], 'crypto' => [], 'cash' => []];

		foreach ($methods as $id => $method) {
			if (empty($method['status'])) {
				continue;
			}
			$method['id'] = $id;
			$category = $method['category'] ?? 'crypto';
			if (!isset($grouped[$category])) {
				$grouped[$category] = [];
				$groupsMeta[$category] = [];
			}
			$groupKey = $method['group'] ?? '_none';
			$grouped[$category][$groupKey][$id] = $method;

			if ($groupKey !== '_none' && !isset($groupsMeta[$category][$groupKey])) {
				$groupsMeta[$category][$groupKey] = [
					'label' => $method['group_label'] ?? ucfirst($groupKey),
					'image' => $method['group_image'] ?? $method['image'],
				];
			}
		}

		return ['methods' => $grouped, 'groups' => $groupsMeta];
	}

	/**
	 * Looks up one method by id (mirrors the old m_core->getCurrency()).
	 */
	private function get_method($id)
	{
		$methods = $this->load_methods();
		if (!isset($methods[$id])) {
			return false;
		}
		$method = $methods[$id];
		$method['id'] = $id;
		return $method;
	}

	public function index()
	{
		$this->data['page'] = 'Withdraw';

		// Hardcoded withdraw rate — see the COIN_TO_USD_RATE constant above.
		$this->data['settings']['currency_rate'] = self::COIN_TO_USD_RATE;

		$this->data['task_history'] = $this->m_withdraw->get_task_history($this->data['user']['id']);
		$this->data['lottery_history'] = $this->m_withdraw->get_lottery_history($this->data['user']['id']);
		$this->data['offerwall_history'] = $this->m_withdraw->get_offerwall_history($this->data['user']['id']);
		$this->data['withdrawals_history'] = $this->m_withdraw->get_withdrawals_history($this->data['user']['id']);
		$this->data['referrals'] = $this->m_withdraw->getReferrals($this->data['user']['id']);
		$this->data['referralCount'] = $this->m_withdraw->get_ref($this->data['user']['id']);

		// Manual methods, grouped by category (+ sub-group) instead of the old
		// DB query: $this->db->get_where('currencies', ['status' => 1])->result_array();
		$active = $this->get_active_methods();
		$this->data['methods'] = $active['methods'];
		$this->data['method_groups'] = $active['groups'];

		// How much of today's daily withdraw limit the user has already used,
		// so the view can render a "daily limit" progress bar.
		$this->data['today_withdraw_amount'] = $this->m_withdraw->getTotalWithdrawToday($this->data['user']['id']);

		$this->data['bonus'] = min($this->data['settings']['max_bonus'], $this->data['settings']['level_bonus'] * $this->data['user']['level']);
		$this->render('withdraw', $this->data);
	}

	public function withdraw()
	{
		// Hardcoded withdraw rate — see the COIN_TO_USD_RATE constant above.
		$this->data['settings']['currency_rate'] = self::COIN_TO_USD_RATE;

		if ($this->data['user']['status'] == 'banned') {
			$this->session->set_flashdata('sweet_message', faucet_sweet_alert('error', 'You are banned!'));
			return redirect(site_url('/withdraw'));
		}
		$this->form_validation->set_rules('amount', 'Amount', 'trim|required|is_numeric|greater_than[0]');
		$this->form_validation->set_rules('method', 'Method', 'trim|required|integer');
		$this->form_validation->set_rules('wallet', 'Wallet', 'trim|required|max_length[60]');


		if ($this->form_validation->run() == FALSE) {
			$this->session->set_flashdata('sweet_message', faucet_sweet_alert('error', validation_errors()));
			return redirect(site_url('/withdraw'));
		}

		$usdAmount = format_money($this->input->post('amount') * $this->data['settings']['currency_rate']);

		if ($usdAmount > $this->data['user']['balance']) {
			$this->session->set_flashdata('sweet_message', faucet_sweet_alert('warning', 'That amount is more than your current balance.'));
			return redirect(site_url('/withdraw'));
		}

		$todayWithdrawAmount = $this->m_withdraw->getTotalWithdrawToday($this->data['user']['id']);
		if ($todayWithdrawAmount + $usdAmount > $this->data['settings']['withdraw_limit']) {
			$this->session->set_flashdata('sweet_message', faucet_sweet_alert('error', 'Daily withdraw limit reached!'));
			return redirect(site_url('/withdraw'));
		}
		$wallet = $this->db->escape_str($this->input->post('wallet'));
		$sameWallet = $this->m_withdraw->checkSameWallet($this->data['user']['id'], $wallet);

		if ($sameWallet) {
			foreach ($sameWallet as $cheater) {
				$this->m_core->updateStatus($cheater['user_id'], 'suspect');
				$this->m_core->insertCheatLog($cheater['user_id'], "Same wallet to other account: " . $wallet, $this->input->ip_address());
			}
			$this->m_core->updateStatus($this->data['user']['id'], 'suspect');
			$this->m_core->insertCheatLog($this->data['user']['id'],  "Same wallet to other account: " . $wallet, $this->input->ip_address());
			$this->session->set_flashdata('sweet_message', faucet_sweet_alert('error', 'This wallet address is already linked to another account. Both accounts have been flagged for review — contact support if this is a mistake.'));
			return redirect(site_url('/withdraw'));
		}

		// Manual method lookup instead of: $this->m_core->getCurrency($this->input->post('method'));
		$method = $this->get_method($this->input->post('method'));
		if (!$method || empty($method['status'])) {
			$this->session->set_flashdata('sweet_message', faucet_sweet_alert('error', 'That withdrawal method is not available. Please pick a method again.'));
			return redirect(site_url('withdraw'));
		}

		$satoshiAmount = floor($usdAmount * 100000000 / $method['price']);

		if ($usdAmount == 0 || $usdAmount < $method['minimum_withdrawal']) {
			$this->session->set_flashdata('sweet_message', faucet_sweet_alert('warning', 'Minimum withdrawal is ' . currency($method['minimum_withdrawal'], $this->data['settings']['currency_rate'])));
			return redirect(site_url('/withdraw'));
		}

		// Fixed-quantity packages (Free Fire diamonds, PUBG UC, Visa/PayPal cards, ...)
		// must match their exact price — a user can't "top up" a package by
		// sending extra coins, and can't send less either. The front-end
		// already locks the amount for these, this is the server-side guard.
		if (!empty($method['fixed'])) {
			$expectedUsd = (float) $method['minimum_withdrawal'];
			if (abs($usdAmount - $expectedUsd) > self::FIXED_AMOUNT_EPSILON) {
				$this->session->set_flashdata('sweet_message', faucet_sweet_alert('error', 'That package amount is no longer valid. Please select the package again.'));
				return redirect(site_url('/withdraw'));
			}
		}


		if ($method['wallet'] == 'faucetpay') {
			$hash = $this->data['user']['fp_hash'];
			if ($this->data['user']['fp_hash'] == 'none') {
				$check = fpCheck($wallet, $method['api'], $method['code']);
				if ($check['status'] !== 200) {
					$this->session->set_flashdata('sweet_message', faucet_sweet_alert('warning', 'Your address is not linked to your FaucetPay account' . currency($method['minimum_withdrawal'], $this->data['settings']['currency_rate'])));
					return redirect(site_url('/withdraw'));
				} else {
					$hash = $check['payout_user_hash'];
					$this->m_withdraw->updateFPHash($this->data['user']['id'], $check['payout_user_hash']);
				}
			}
			$checkHash = $this->m_hidden->checkFpHash($hash);
			if ($checkHash) {
				foreach ($checkHash as $id) {
					$this->m_core->updateStatus($id['id'], 'suspect');
					$this->m_core->insertCheatLog($id['id'], "Same FaucetPay to other account", $this->input->ip_address());
				}
				return redirect(site_url('/withdraw'));
			}
			if ($this->data['settings']['instant_withdraw'] == 'on') {
				$result = faucetpay($wallet, $this->input->ip_address(), $satoshiAmount, $method['api'], $method['code'], $referral = false);
				if ($result["status"] == 200 && $usdAmount < '0.4' ) {
					$this->m_withdraw->reduceBalance($this->data['user']['id'], $usdAmount);
					$this->m_withdraw->insert_history($this->data['user']['id'], 1, $method['id'], $wallet, $usdAmount);
					$this->session->set_flashdata('sweet_message', faucet_sweet_alert('success', currency($usdAmount, $this->data['settings']['currency_rate']) . ' has been sent to your account!'));
					if ($this->data['user']['fp_hash'] == 'none') {
						$this->m_withdraw->updateFPHash($this->data['user']['id'], $result['payout_user_hash']);
					}
				} else {
					$this->session->set_flashdata('sweet_message', faucet_sweet_alert('warning', $result['message']));
				}
			} else {
				$this->m_withdraw->reduceBalance($this->data['user']['id'], $usdAmount);
				$this->m_withdraw->insert_history($this->data['user']['id'], 0, $method['id'], $wallet, $usdAmount);
				$this->session->set_flashdata('sweet_message', faucet_sweet_alert('success', 'You have sent a withdrawal request successfully!'));
			}
		} else if ($method['wallet'] == 'expresscrypto') {
			if ($this->data['settings']['instant_withdraw'] == 'on') {
				include APPPATH . 'third_party/expresscrypto.php';
				$expresscrypto = new ExpressCryptoV2($method['api'], $method['token'], $this->input->ip_address());
				$result = $expresscrypto->sendPayment($wallet, $method['code'], $satoshiAmount);
				if ($result["status"] == 200) {
					$this->m_withdraw->reduceBalance($this->data['user']['id'], $usdAmount);
					$this->m_withdraw->insert_history($this->data['user']['id'], 1, $method['id'], $wallet, $usdAmount);
					$this->session->set_flashdata('sweet_message', faucet_sweet_alert('success', currency($usdAmount, $this->data['settings']['currency_rate']) . ' has been sent to your account!'));
				} else {
					$this->session->set_flashdata('sweet_message', faucet_sweet_alert('warning', $result['message']));
				}
			} else {
				$this->m_withdraw->reduceBalance($this->data['user']['id'], $usdAmount);
				$this->m_withdraw->insert_history($this->data['user']['id'], 0, $method['id'], $wallet, $usdAmount);
				$this->session->set_flashdata('sweet_message', faucet_sweet_alert('success', 'You have sent a withdrawal request successfully!'));
			}
		} else if ($method['wallet'] == 'payeer') {
			if ($this->data['settings']['instant_withdraw'] == 'on') {
				include APPPATH . 'third_party/payeer.php';
				$payeer = new CPayeer($method['account_number'], $method['api_id'], $method['api']);
				if ($payeer->isAuth()) {
					$arTransfer = $payeer->transfer(array(
						'curIn' => 'USD',
						'sum' => $usdAmount,
						'curOut' => $method['code'],
						'to' => $wallet,
						'comment' => 'Payment from' . $this->data['settings']['name']
					));
					if (empty($arTransfer['errors'])) {
						$this->m_withdraw->reduceBalance($this->data['user']['id'], $usdAmount);
						$this->m_withdraw->insert_history($this->data['user']['id'], 1, $method['id'], $wallet, $usdAmount);
						$this->session->set_flashdata('sweet_message', faucet_sweet_alert('success', currency($usdAmount, $this->data['settings']['currency_rate']) . ' has been sent to your account!'));
					} else {
						$this->session->set_flashdata('sweet_message', faucet_sweet_alert('warning', 'Error! Please try again (' . $arTransfer["errors"][0] . ')'));
					}
				} else {
					$this->session->set_flashdata('sweet_message', faucet_sweet_alert('warning', 'Error! Please try again (' . $payeer->getErrors()[0] . ')'));
				}
			} else {
				$this->m_withdraw->reduceBalance($this->data['user']['id'], $usdAmount);
				$this->m_withdraw->insert_history($this->data['user']['id'], 0, $method['id'], $wallet, $usdAmount);
				$this->session->set_flashdata('sweet_message', faucet_sweet_alert('success', 'Sent withdraw request'));
			}
		} else if ($method['wallet'] == 'custom') {
			$this->m_withdraw->reduceBalance($this->data['user']['id'], $usdAmount);
			$this->m_withdraw->insert_history($this->data['user']['id'], 0, $method['id'], $wallet, $usdAmount);
			$this->session->set_flashdata('sweet_message', faucet_sweet_alert('success', 'You have sent a withdrawal request successfully!'));
		}
		if ($wallet != $this->data['user']['wallet']) {
			$this->m_withdraw->update_wallet($this->data['user']['id'], $this->db->escape_str($wallet));
		}
		return redirect(site_url('/withdraw'));
	}

	public function read_notifications()
	{
		$this->m_withdraw->readAllNotifications($this->data['user']['id']);
	}

	public function resend()
	{
		if ($this->data['user']['verified'] == 1) {
			return redirect(site_url('/withdraw'));
		}
		$siteName = $this->data['settings']['name'];
		$activeUrl = site_url('/active/' . $this->data['user']['secret']);
		$message = <<<EOT
			<table class="body-wrap" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; background-color: transparent; margin: 0;">
			<tbody><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
			<td style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;" valign="top"></td>
			<td class="container" width="600" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; display: block !important; max-width: 600px !important; clear: both !important; margin: 0 auto;" valign="top">
				<div class="content" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; max-width: 600px; display: block; margin: 0 auto; padding: 20px;">
					<table class="main" width="100%" cellpadding="0" cellspacing="0" itemprop="action" itemscope="" itemtype="http://schema.org/ConfirmAction" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; border-radius: 3px; margin: 0; border: none;">
						<tbody><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
							<td class="content-wrap" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; color: #495057; font-size: 14px; vertical-align: top; margin: 0;padding: 30px; box-shadow: 0 0.75rem 1.5rem rgba(18,38,63,.03); ;border-radius: 7px; background-color: #fff;" valign="top">
								<meta itemprop="name" content="Confirm Email" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
								<table width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
									<tbody><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
										<td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
											Welcome to $siteName. Please confirm your email address by clicking the link below.
										</td>
									</tr>
									<tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
										<td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
											You won't be able to withdraw until you have verified your account.
										</td>
									</tr>
									<tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
										<td class="content-block" itemprop="handler" itemscope="" itemtype="http://schema.org/HttpActionHandler" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
											<a href="$activeUrl" itemprop="url" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; color: #FFF; text-decoration: none; line-height: 2em; font-weight: bold; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; text-transform: capitalize; background-color: #34c38f; margin: 0; border-color: #34c38f; border-style: solid; border-width: 8px 16px;">Confirm email address</a>
										</td>
									</tr>
									<tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
										<td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
											<b>$siteName</b>
											<p>Support Team</p>
										</td>
									</tr>
								</tbody>
								</table>
							</td>
						</tr>
					</tbody></table>
				</div>
			</td>
		</tr>
	</tbody></table>
EOT;

		if (sendMail($this->data['user']['email'], 'Active your account', $message, $this->data['settings'])) {
			$this->session->set_flashdata('message', faucet_alert('success', 'Email sent'));
		} else {
			$this->session->set_flashdata('message', faucet_alert('danger', 'Failed to sent email'));
		}
		return redirect(site_url('/withdraw'));
	}
}