<?php

declare(strict_types=1);

namespace App\Http\Controllers\Market;

use App\Http\Controllers\Helpers\ResponseHelper;
use App\Http\Controllers\Helpers\PaymentProcessor;
use App\Http\Controllers\Helpers\QrphDecoder;
use App\Models\SystemSetting;
use App\Models\Accounting\MemberLedger;
use App\Models\User;
use App\Models\GlobalTransaction;
use Hypervel\Http\Request;
use Hypervel\Support\Facades\Auth;
use Hypervel\Support\Facades\DB;
use Hypervel\Support\Str;
use App\Enums\Market\ProductTransactionType;
use App\Enums\Market\TransactionFlow;

class CreditController
{
    public function getWalletData(Request $request)
    {
        $user = User::find(Auth::id());
        if (!$user) return ResponseHelper::returnUnauthorized();

        $history = MemberLedger::where('user_id', $user->id)
            ->where('is_active', true)
            ->orderBy('created_at', 'desc')
            ->limit(20)
            ->get();

        return response()->json([
            'success' => true,
            'balance' => $user->total_balance,
            'credit' => $user->total_credit,
            'history' => $history
        ]);
    }

    public function topUp(Request $request)
    {
        // Check if Top Up is enabled globally
        if (!(\App\Models\SystemSetting::getValue('top_up_enabled', true))) {
            return ResponseHelper::returnError('Credit top-up is currently disabled by administrators.');
        }

        $amount = (float) $request->input('amount');
        $method = $request->input('method', 'GCASH');
        
        if ($amount <= 0) {
            return ResponseHelper::returnError('Amount must be greater than zero');
        }

        $user = User::find(Auth::id());
        if (!$user) return ResponseHelper::returnUnauthorized();

        // Start Transaction
        DB::beginTransaction();
        try {
            // 1. Simulate Payment Success (in real life this would be a webhook/callback)
            $payment = PaymentProcessor::initiatePayment($amount, $method, $user->hashkey);
            
            if (!$payment['success']) {
                throw new \Exception('Payment initiation failed');
            }

            // 2. Update User Balance
            $user->total_balance += $amount;
            $user->save();

            // 3. Record in MemberLedger
            $ledger = new MemberLedger([
                'hashkey' => Str::random(64),
                'user_id' => $user->id,
                'amount' => $amount,
                'transaction_type' => 'TOP_UP',
                'flow' => 'IN',
                'balance_after' => $user->total_balance,
                'description' => "Credit Top-up via {$method}",
                'reference_id' => $payment['transaction_id'],
                'created_by' => $user->id,
                'is_active' => true,
            ]);
            $ledger->save();

            // 4. Record in GlobalTransaction (for compatibility with existing reports)
            $globalTxn = new GlobalTransaction([
                'hashkey' => Str::random(64),
                'user_id' => $user->id,
                'amount' => $amount,
                'type' => ProductTransactionType::TOP_UP,
                'status' => 'COMPLETED',
                'description' => "Credit Top-up via {$method}",
                'flow' => TransactionFlow::INCOME,
                'created_by' => $user->id,
            ]);
            $globalTxn->save();

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Top-up successful',
                'balance' => $user->total_balance,
                'transaction_id' => $payment['transaction_id']
            ]);

        } catch (\Exception $e) {
            DB::rollBack();
            return ResponseHelper::returnError('Top-up failed: ' . $e->getMessage());
        }
    }

    public function transferCredit(Request $request)
    {
        $recipientHash = $request->input('recipient_hash');
        $amount = (float) $request->input('amount');

        if ($amount <= 0) return ResponseHelper::returnError('Invalid amount');

        $sender = User::find(Auth::id());
        if (!$sender) return ResponseHelper::returnUnauthorized();

        if ($sender->total_balance < $amount) {
            return ResponseHelper::returnError('Insufficient balance');
        }

        $recipient = User::where('hashkey', $recipientHash)->first();
        if (!$recipient) return ResponseHelper::returnError('Recipient not found');

        if ($sender->id === $recipient->id) {
            return ResponseHelper::returnError('Cannot transfer to yourself');
        }

        DB::beginTransaction();
        try {
            // Deduct from sender
            $sender->total_balance -= $amount;
            $sender->save();

            // Add to recipient
            $recipient->total_balance += $amount;
            $recipient->save();

            $txnRef = Str::random(12);

            // Record Ledger for Sender
            MemberLedger::create([
                'hashkey' => Str::random(64),
                'user_id' => $sender->id,
                'amount' => $amount,
                'transaction_type' => 'TRANSFER_OUT',
                'flow' => 'OUT',
                'balance_after' => $sender->total_balance,
                'description' => "Credit Transfer to {$recipient->fullname}",
                'reference_id' => $txnRef,
                'created_by' => $sender->id,
            ]);

            // Record Ledger for Recipient
            MemberLedger::create([
                'hashkey' => Str::random(64),
                'user_id' => $recipient->id,
                'amount' => $amount,
                'transaction_type' => 'TRANSFER_IN',
                'flow' => 'IN',
                'balance_after' => $recipient->total_balance,
                'description' => "Credit Transfer from {$sender->fullname}",
                'reference_id' => $txnRef,
                'created_by' => $sender->id,
            ]);

            DB::commit();
            return response()->json(['success' => true, 'message' => 'Transfer successful']);

        } catch (\Exception $e) {
            DB::rollBack();
            return ResponseHelper::returnError('Transfer failed');
        }
    }

    public function searchUsers(Request $request)
    {
        $query = $request->input('q');
        if (empty($query)) return response()->json(['success' => true, 'data' => []]);

        $users = User::where('fullname', 'like', "%{$query}%")
            ->orWhere('name', 'like', "%{$query}%")
            ->orWhere('mobile_number', 'like', "%{$query}%")
            ->where('id', '!=', Auth::id())
            ->limit(10)
            ->get(['hashkey', 'fullname', 'name', 'mobile_number']);

        return response()->json(['success' => true, 'data' => $users]);
    }

    /**
     * GET the current QRPH payment code (available to all authenticated users for top-up display).
     */
    public function getQrphCode(Request $request)
    {
        $raw        = SystemSetting::getValue('qrph_payment_code', null);
        $imgHashkey = SystemSetting::getValue('qrph_payment_image_hashkey', null);

        if (empty($raw)) {
            return response()->json(['success' => true, 'qrph' => null, 'decoded' => null, 'image_url' => null]);
        }

        $decoded  = QrphDecoder::decode($raw);
        $imageUrl = $imgHashkey ? "/RequestData/File/{$imgHashkey}" : null;

        return response()->json([
            'success'   => true,
            'qrph'      => $raw,
            'decoded'   => $decoded,
            'image_url' => $imageUrl,
        ]);
    }

    /**
     * SET the QRPH payment code — ULTIMATE only (enforced by route middleware).
     * Accepts optional image_hashkey from a prior /File/Upload/QrphPayment call.
     */
    public function setQrphCode(Request $request)
    {
        $raw        = trim($request->input('qrph_code', ''));
        $imgHashkey = trim($request->input('image_hashkey', ''));

        if (empty($raw)) {
            SystemSetting::setValue('qrph_payment_code', '');
            SystemSetting::setValue('qrph_payment_image_hashkey', '');
            return response()->json(['success' => true, 'message' => 'QRPH code cleared.']);
        }

        $decoded = QrphDecoder::decode($raw);

        SystemSetting::setValue('qrph_payment_code', $raw);
        if (!empty($imgHashkey)) {
            SystemSetting::setValue('qrph_payment_image_hashkey', $imgHashkey);
        }

        $imageUrl = $imgHashkey ? "/RequestData/File/{$imgHashkey}" : null;

        return response()->json([
            'success'   => true,
            'message'   => 'QRPH code saved.',
            'decoded'   => $decoded,
            'image_url' => $imageUrl,
        ]);
    }

    /**
     * Decode a QRPH string without saving — for preview before saving.
     */
    public function decodeQrph(Request $request)
    {
        $raw = trim($request->input('qrph_code', ''));
        if (empty($raw)) {
            return ResponseHelper::returnError('No QR string provided.');
        }

        return response()->json([
            'success' => true,
            'decoded' => QrphDecoder::decode($raw),
        ]);
    }
}
