<?php

namespace App\Controllers;

use App\Models\InternetPayment;
use App\Models\MpesaTransaction;
use App\Services\MpesaService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;

class MpesaController extends Controller
{
    /**
     * Show M-Pesa payment form
     */
    public function showPaymentForm($paymentId)
    {
        try {
            $payment = InternetPayment::with('station')->findOrFail($paymentId);
            
            if ($payment->status === 'paid') {
                return redirect()->route('payments.internet.show', $payment->id)
                    ->with('warning', 'This payment has already been completed');
            }
            
            $existingTransaction = MpesaTransaction::where('payment_id', $payment->id)
                ->where('status', 'pending')
                ->first();
            
            return view('payments.mpesa-payment', compact('payment', 'existingTransaction'));
            
        } catch (\Exception $e) {
            Log::error('Failed to load M-Pesa payment form: ' . $e->getMessage());
            return redirect()->back()->with('error', 'Unable to load payment form');
        }
    }

    /**
     * Initiate M-Pesa STK Push
     */
    public function initiateMpesaPayment(Request $request, $id)
    {
        try {
            // FIXED: Proper validation rules
            $validated = $request->validate([
                'phone_number' => 'required|string|regex:/^([0-9]{9,12})$/',
                'amount' => 'required|numeric|min:1|max:150000'
            ]);

            $payment = InternetPayment::findOrFail($id);

            // Check if payment is already paid
            if ($payment->status === 'paid') {
                return response()->json([
                    'success' => false,
                    'message' => 'Payment has already been completed'
                ], 422);
            }

            // Format phone number
            $phoneNumber = $this->formatPhoneNumber($validated['phone_number']);
            
            // Validate formatted phone number
            if (!preg_match('/^254[0-9]{9}$/', $phoneNumber)) {
                return response()->json([
                    'success' => false,
                    'message' => 'Invalid phone number format. Use 0712345678 or 254712345678'
                ], 422);
            }

            $mpesaService = new MpesaService();
            $response = $mpesaService->stkPush(
                $phoneNumber,
                $validated['amount'],
                $payment->account_number,
                'Internet Payment for ' . ($payment->station->name ?? 'Station')
            );

            if ($response->ResponseCode == '0') {
                // Store transaction
                $transaction = MpesaTransaction::create([
                    'checkout_request_id' => $response->CheckoutRequestID,
                    'payment_id' => $payment->id,
                    'phone_number' => $phoneNumber,
                    'amount' => $validated['amount'],
                    'status' => 'pending',
                    'merchant_request_id' => $response->MerchantRequestID ?? null,
                    'response_code' => $response->ResponseCode,
                    'response_description' => $response->ResponseDescription ?? null
                ]);

                return response()->json([
                    'success' => true,
                    'message' => 'STK Push initiated successfully',
                    'data' => [
                        'checkout_request_id' => $response->CheckoutRequestID,
                        'transaction_id' => $transaction->id
                    ]
                ]);
            } else {
                return response()->json([
                    'success' => false,
                    'message' => $response->ResponseDescription ?? 'Failed to initiate payment'
                ], 400);
            }
            
        } catch (ValidationException $e) {
            // FIXED: Return validation errors in proper format
            return response()->json([
                'success' => false,
                'message' => 'Validation failed',
                'errors' => $e->errors()
            ], 422);
            
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return response()->json([
                'success' => false,
                'message' => 'Payment not found'
            ], 404);
            
        } catch (\Exception $e) {
            Log::error('M-Pesa STK Push Error: ' . $e->getMessage(), [
                'trace' => $e->getTraceAsString()
            ]);
            
            return response()->json([
                'success' => false,
                'message' => 'Failed to initiate M-Pesa payment: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Format phone number to international format
     */
    private function formatPhoneNumber($phoneNumber)
    {
        // Remove any non-numeric characters
        $phoneNumber = preg_replace('/[^0-9]/', '', $phoneNumber);
        
        // Remove leading 0 or 254 if present and add 254
        if (substr($phoneNumber, 0, 1) == '0') {
            $phoneNumber = '254' . substr($phoneNumber, 1);
        } elseif (substr($phoneNumber, 0, 3) == '254') {
            $phoneNumber = $phoneNumber;
        } elseif (substr($phoneNumber, 0, 4) == '2540') {
            $phoneNumber = '254' . substr($phoneNumber, 4);
        } else {
            $phoneNumber = '254' . $phoneNumber;
        }
        
        return $phoneNumber;
    }

    /**
     * Check M-Pesa transaction status
     */
    public function checkMpesaTransaction($checkoutRequestId)
    {
        try {
            $transaction = MpesaTransaction::where('checkout_request_id', $checkoutRequestId)
                ->with('payment')
                ->first();

            if (!$transaction) {
                return response()->json([
                    'status' => 'not_found',
                    'message' => 'Transaction not found'
                ], 404);
            }

            $responseData = ['status' => $transaction->status];

            if ($transaction->status === 'completed') {
                $responseData['mpesa_receipt'] = $transaction->mpesa_receipt;
                $responseData['amount'] = $transaction->amount;
                $responseData['payment_status'] = $transaction->payment->status ?? null;
            } elseif ($transaction->status === 'failed') {
                $responseData['message'] = $transaction->result_desc ?? 'Payment failed';
            }

            return response()->json($responseData);

        } catch (\Exception $e) {
            Log::error('Check Transaction Error: ' . $e->getMessage());
            return response()->json([
                'status' => 'error',
                'message' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * M-Pesa Callback Handler
     */
    public function mpesaCallback(Request $request)
    {
        Log::info('M-Pesa Callback Received:', $request->all());

        try {
            $data = $request->Body->stkCallback;
            $checkoutRequestId = $data->CheckoutRequestID;

            $transaction = MpesaTransaction::where('checkout_request_id', $checkoutRequestId)
                ->with('payment')
                ->first();

            if (!$transaction) {
                Log::error('Transaction not found for CheckoutRequestID: ' . $checkoutRequestId);
                return response()->json(['ResultCode' => 1, 'ResultDesc' => 'Transaction not found']);
            }

            if ($data->ResultCode == 0) {
                // Payment successful
                $callbackData = $data->CallbackMetadata->Item;
                $mpesaReceipt = '';

                foreach ($callbackData as $item) {
                    if ($item->Name == 'MpesaReceiptNumber') {
                        $mpesaReceipt = $item->Value;
                        break;
                    }
                }

                $transaction->update([
                    'status' => 'completed',
                    'mpesa_receipt' => $mpesaReceipt,
                    'result_code' => $data->ResultCode,
                    'result_desc' => $data->ResultDesc ?? 'Success'
                ]);

                // Update payment
                $payment = $transaction->payment;
                if ($payment && $payment->status !== 'paid') {
                    $payment->update([
                        'status' => 'paid',
                        'payment_date' => now()->format('Y-m-d'),
                        'payment_method' => 'M-Pesa',
                        'mpesa_receipt' => $mpesaReceipt,
                        'transaction_id' => $mpesaReceipt
                    ]);

                    Log::info('Payment updated successfully', [
                        'payment_id' => $payment->id,
                        'mpesa_receipt' => $mpesaReceipt
                    ]);
                }

                return response()->json(['ResultCode' => 0, 'ResultDesc' => 'Success']);
            } else {
                // Payment failed
                $transaction->update([
                    'status' => 'failed',
                    'result_code' => $data->ResultCode,
                    'result_desc' => $data->ResultDesc ?? 'Payment failed'
                ]);

                Log::info('Transaction failed', [
                    'checkout_request_id' => $checkoutRequestId,
                    'result_code' => $data->ResultCode,
                    'result_desc' => $data->ResultDesc ?? 'No description'
                ]);

                return response()->json(['ResultCode' => 1, 'ResultDesc' => 'Payment failed']);
            }
        } catch (\Exception $e) {
            Log::error('M-Pesa Callback Error: ' . $e->getMessage(), [
                'trace' => $e->getTraceAsString()
            ]);

            return response()->json([
                'ResultCode' => 1,
                'ResultDesc' => 'Internal server error: ' . $e->getMessage()
            ]);
        }
    }
}