<?php
// app/Http\Controllers\Api\Customer\PaymentController.php
namespace App\Http\Controllers\Api\Customer;

use App\Http\Controllers\Controller;
use App\Http\Requests\Api\Customer\PaymentRequest;
use App\Http\Requests\Api\Customer\UploadProofRequest;
use App\Http\Resources\Api\Customer\PaymentMethodResource;
use App\Http\Resources\Api\Customer\PaymentResource;
use App\Models\Order;
use App\Models\Payment;
use App\Models\PaymentMethod;
use App\Traits\ApiResponse;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;

class PaymentController extends Controller
{
    use ApiResponse;

    /**
     * Get available payment methods
     * GET /api/customer/payment-methods
     */
    public function getPaymentMethods(): JsonResponse
    {
        $methods = PaymentMethod::active()->orderBy('name')->get();
        
        return $this->successResponse([
            'payment_methods' => PaymentMethodResource::collection($methods),
            'instructions' => [
                'cash' => 'Bayar langsung di kasir saat mengambil pesanan',
                'bank_transfer' => 'Upload bukti transfer setelah pembayaran',
                'ewallet' => 'Screenshot bukti pembayaran dan upload',
                'qris' => 'Scan QRIS di tempat atau aplikasi',
                'credit_card' => 'Bayar dengan kartu di tempat atau online',
            ]
        ], 'Metode pembayaran berhasil diambil');
    }

    /**
     * Create payment for order
     * POST /api/customer/orders/{order_id}/payments
     */
    public function store(PaymentRequest $request, $orderId): JsonResponse
    {
        DB::beginTransaction();
        
        try {
            $user = $request->user();
            
            $order = Order::where('customer_id', $user->id)
                        ->where('id', $orderId)
                        ->first();

            if (!$order) {
                return $this->errorResponse('Pesanan tidak ditemukan', 404);
            }

            if ($order->status === 'cancelled') {
                return $this->errorResponse('Pesanan telah dibatalkan', 400);
            }

            if (!in_array($order->status, ['pending', 'confirmed'])) {
                return $this->errorResponse('Pesanan tidak dapat diproses untuk pembayaran', 400);
            }

            // Check if payment already exists
            $existingPayment = Payment::where('order_id', $orderId)
                                    ->whereIn('status', ['pending', 'waiting_confirmation', 'confirmed'])
                                    ->first();

            if ($existingPayment) {
                return $this->successResponse(
                    new PaymentResource($existingPayment->load(['order', 'paymentMethod'])),
                    'Sudah ada pembayaran untuk pesanan ini'
                );
            }

            $paymentMethod = PaymentMethod::find($request->payment_method_id);
            if (!$paymentMethod || !$paymentMethod->is_active) {
                return $this->errorResponse('Metode pembayaran tidak tersedia', 400);
            }

            // Determine initial status based on payment method
            $initialStatus = $paymentMethod->code === 'cash' ? 'confirmed' : 'waiting_confirmation';
            
            $payment = Payment::create([
                'order_id' => $order->id,
                'payment_method_id' => $paymentMethod->id,
                'amount' => $order->final_amount,
                'status' => $initialStatus,
                'payment_date' => $initialStatus === 'confirmed' ? now() : null,
                'reference_number' => $this->generateReferenceNumber($paymentMethod),
            ]);

            // Update order status based on payment
            if ($initialStatus === 'confirmed') {
                $order->update([
                    'status' => 'preparing',
                    'notes' => $order->notes . "\n[Pembayaran tunai dikonfirmasi otomatis]"
                ]);
                
                $payment->update([
                    'confirmed_at' => now(),
                    'confirmed_by' => null, // System auto-confirm
                ]);
            } else {
                $order->update(['status' => 'confirmed']);
            }

            DB::commit();

            return $this->successResponse(
                new PaymentResource($payment->load(['order', 'paymentMethod'])),
                $initialStatus === 'confirmed' 
                    ? '✅ Pembayaran tunai dikonfirmasi otomatis. Pesanan sedang diproses.' 
                    : '💳 Pembayaran berhasil dibuat. Silakan upload bukti pembayaran.',
                201
            );

        } catch (\Exception $e) {
            DB::rollBack();
            return $this->errorResponse('Gagal membuat pembayaran: ' . $e->getMessage(), 500);
        }
    }

    /**
     * Upload payment proof
     * POST /api/customer/payments/{id}/upload-proof
     */
    public function uploadProof(UploadProofRequest $request, $id): JsonResponse
    {
        DB::beginTransaction();
        
        try {
            $payment = Payment::whereHas('order', function ($q) use ($request) {
                $q->where('customer_id', $request->user()->id);
            })->find($id);

            if (!$payment) {
                return $this->errorResponse('Pembayaran tidak ditemukan', 404);
            }

            if (!in_array($payment->status, ['waiting_confirmation', 'pending'])) {
                return $this->errorResponse(
                    'Tidak dapat mengupload bukti. Status pembayaran: ' . $this->getFormattedStatus($payment->status), 
                    400
                );
            }

            // Handle file upload
            $proofPath = null;
            if ($request->hasFile('proof_image')) {
                // Delete old proof if exists
                if ($payment->proof_image && Storage::exists('public/' . $payment->proof_image)) {
                    Storage::delete('public/' . $payment->proof_image);
                }

                // Store new proof
                $fileName = 'proof_' . time() . '_' . $payment->id . '.' . 
                           $request->file('proof_image')->getClientOriginalExtension();
                $path = $request->file('proof_image')->storeAs('payment-proofs', $fileName, 'public');
                $proofPath = $path;
            }

            // Update payment
            $payment->update([
                'proof_image' => $proofPath,
                'status' => 'waiting_confirmation',
                'payment_date' => $request->payment_date ?? now(),
                'reference_number' => $request->reference_number ?? $payment->reference_number,
                'notes' => $request->notes ?? $payment->notes,
            ]);

            DB::commit();

            return $this->successResponse(
                new PaymentResource($payment->fresh(['order', 'paymentMethod'])),
                '✅ Bukti pembayaran berhasil diupload. Menunggu konfirmasi admin (1-2 jam kerja).'
            );

        } catch (\Exception $e) {
            DB::rollBack();
            return $this->errorResponse('Gagal mengupload bukti: ' . $e->getMessage(), 500);
        }
    }

    /**
     * Get payment detail
     * GET /api/customer/payments/{id}
     */
    public function show(Request $request, $id): JsonResponse
    {
        $payment = Payment::with(['order', 'paymentMethod'])
                        ->whereHas('order', function ($q) use ($request) {
                            $q->where('customer_id', $request->user()->id);
                        })
                        ->find($id);

        if (!$payment) {
            return $this->errorResponse('Pembayaran tidak ditemukan', 404);
        }

        $response = new PaymentResource($payment);
        $responseData = $response->toArray($request);
        $responseData['instructions'] = $this->getPaymentInstructions($payment);
        $responseData['next_actions'] = $this->getNextActions($payment);

        return $this->successResponse(
            $responseData,
            'Detail pembayaran berhasil diambil'
        );
    }

    /**
     * Get payment by order ID
     * GET /api/customer/payments/order/{order_id}
     */
    public function getByOrder(Request $request, $orderId): JsonResponse
    {
        $order = Order::where('customer_id', $request->user()->id)
                    ->with(['payments.paymentMethod'])
                    ->find($orderId);

        if (!$order) {
            return $this->errorResponse('Pesanan tidak ditemukan', 404);
        }

        if ($order->payments->isEmpty()) {
            return $this->successResponse([
                'order' => [
                    'id' => $order->id,
                    'order_number' => $order->order_number,
                    'status' => $order->status,
                    'final_amount' => (float) $order->final_amount,
                    'formatted_amount' => 'Rp ' . number_format($order->final_amount, 0, ',', '.'),
                ],
                'payment' => null,
                'message' => 'Belum ada pembayaran untuk pesanan ini'
            ], 'Status pembayaran');
        }

        $payment = $order->payments->first();
        $response = new PaymentResource($payment);
        $responseData = $response->toArray($request);
        $responseData['order'] = [
            'id' => $order->id,
            'order_number' => $order->order_number,
            'status' => $order->status,
        ];

        return $this->successResponse(
            $responseData,
            'Detail pembayaran berhasil diambil'
        );
    }

    /**
     * Get customer's payment history
     * GET /api/customer/payments
     */
    public function index(Request $request): JsonResponse
    {
        $user = $request->user();
        
        $payments = Payment::with(['order', 'paymentMethod'])
            ->whereHas('order', function ($q) use ($user) {
                $q->where('customer_id', $user->id);
            })
            ->when($request->status, function ($query, $status) {
                return $query->where('status', $status);
            })
            ->when($request->date_from && $request->date_to, function ($query) use ($request) {
                return $query->whereBetween('created_at', [
                    $request->date_from . ' 00:00:00',
                    $request->date_to . ' 23:59:59'
                ]);
            })
            ->when($request->payment_method_id, function ($query, $methodId) {
                return $query->where('payment_method_id', $methodId);
            })
            ->orderBy('created_at', 'desc')
            ->paginate($request->per_page ?? 10);

        // Payment statistics
        $stats = $this->getPaymentStatistics($user->id);

        return $this->successResponse([
            'payments' => PaymentResource::collection($payments),
            'pagination' => [
                'total' => $payments->total(),
                'per_page' => $payments->perPage(),
                'current_page' => $payments->currentPage(),
                'last_page' => $payments->lastPage(),
                'from' => $payments->firstItem(),
                'to' => $payments->lastItem(),
            ],
            'statistics' => $stats,
            'filters' => [
                'status' => $request->status,
                'date_from' => $request->date_from,
                'date_to' => $request->date_to,
                'payment_method_id' => $request->payment_method_id,
            ]
        ], 'Riwayat pembayaran berhasil diambil');
    }

    /**
     * Get pending payments (need action)
     * GET /api/customer/payments/pending
     */
    public function pendingPayments(Request $request): JsonResponse
    {
        $user = $request->user();
        
        $pendingPayments = Payment::with(['order', 'paymentMethod'])
            ->whereHas('order', function ($q) use ($user) {
                $q->where('customer_id', $user->id);
            })
            ->whereIn('status', ['pending', 'waiting_confirmation'])
            ->orderBy('created_at', 'asc')
            ->get();

        // Check for overdue payments (older than 24 hours)
        $overduePayments = $pendingPayments->filter(function ($payment) {
            return $payment->created_at->addHours(24)->isPast() && 
                   $payment->status === 'waiting_confirmation';
        });

        return $this->successResponse([
            'payments' => PaymentResource::collection($pendingPayments),
            'counts' => [
                'total_pending' => $pendingPayments->count(),
                'pending' => $pendingPayments->where('status', 'pending')->count(),
                'waiting_confirmation' => $pendingPayments->where('status', 'waiting_confirmation')->count(),
                'overdue' => $overduePayments->count(),
            ],
            'overdue_payments' => PaymentResource::collection($overduePayments),
            'instructions' => [
                'pending' => 'Silakan pilih metode pembayaran dan lanjutkan',
                'waiting_confirmation' => 'Bukti pembayaran sedang diverifikasi admin',
                'overdue' => '⚠️ Pembayaran melebihi batas waktu 24 jam. Silakan hubungi admin.',
            ]
        ], 'Pembayaran yang memerlukan tindakan');
    }

    /**
     * Resend payment notification
     * POST /api/customer/payments/{id}/resend-notification
     */
    public function resendNotification(Request $request, $id): JsonResponse
    {
        $payment = Payment::whereHas('order', function ($q) use ($request) {
            $q->where('customer_id', $request->user()->id);
        })->find($id);

        if (!$payment) {
            return $this->errorResponse('Pembayaran tidak ditemukan', 404);
        }

        if ($payment->status !== 'waiting_confirmation') {
            return $this->errorResponse('Hanya pembayaran dengan status "Menunggu Konfirmasi" yang dapat mengirim notifikasi', 400);
        }

        // Update timestamp to simulate notification
        $payment->touch();

        return $this->successResponse(
            new PaymentResource($payment->fresh()),
            '✅ Notifikasi telah dikirim ulang ke admin'
        );
    }

    /**
     * Get detailed payment instructions
     * GET /api/customer/payments/{id}/instructions
     */
    public function getInstructions(Request $request, $id): JsonResponse
    {
        $payment = Payment::with(['paymentMethod'])
            ->whereHas('order', function ($q) use ($request) {
                $q->where('customer_id', $request->user()->id);
            })
            ->find($id);

        if (!$payment) {
            return $this->errorResponse('Pembayaran tidak ditemukan', 404);
        }

        $instructions = $this->generateDetailedInstructions($payment);

        return $this->successResponse([
            'payment' => [
                'id' => $payment->id,
                'order_id' => $payment->order_id,
                'amount' => (float) $payment->amount,
                'formatted_amount' => 'Rp ' . number_format($payment->amount, 0, ',', '.'),
                'status' => $payment->status,
                'payment_method' => $payment->paymentMethod->name,
            ],
            'instructions' => $instructions['steps'],
            'important_notes' => $instructions['notes'],
            'deadline' => $payment->created_at->addHours(24)->format('Y-m-d H:i:s'),
            'time_remaining' => now()->diffInHours($payment->created_at->addHours(24), false) . ' jam',
        ], 'Instruksi pembayaran detail');
    }

    // ==================== HELPER METHODS ====================

    /**
     * Generate reference number for payment
     */
    private function generateReferenceNumber(PaymentMethod $method): string
    {
        $prefix = match($method->code) {
            'bank_transfer' => 'BT',
            'ewallet' => 'EW',
            'qris' => 'QR',
            'credit_card' => 'CC',
            'cash' => 'CA',
            default => 'PY'
        };

        return $prefix . date('Ymd') . strtoupper(uniqid());
    }

    /**
     * Get payment statistics for user
     */
    private function getPaymentStatistics($userId): array
    {
        return [
            'total' => Payment::whereHas('order', function ($q) use ($userId) {
                $q->where('customer_id', $userId);
            })->count(),
            'pending' => Payment::whereHas('order', function ($q) use ($userId) {
                $q->where('customer_id', $userId);
            })->where('status', 'pending')->count(),
            'waiting_confirmation' => Payment::whereHas('order', function ($q) use ($userId) {
                $q->where('customer_id', $userId);
            })->where('status', 'waiting_confirmation')->count(),
            'confirmed' => Payment::whereHas('order', function ($q) use ($userId) {
                $q->where('customer_id', $userId);
            })->where('status', 'confirmed')->count(),
            'failed' => Payment::whereHas('order', function ($q) use ($userId) {
                $q->where('customer_id', $userId);
            })->where('status', 'failed')->count(),
            'total_amount' => Payment::whereHas('order', function ($q) use ($userId) {
                $q->where('customer_id', $userId);
            })->where('status', 'confirmed')->sum('amount'),
        ];
    }

    /**
     * Get formatted status text
     */
    private function getFormattedStatus($status): string
    {
        $statuses = [
            'pending' => 'Menunggu Pembayaran',
            'waiting_confirmation' => 'Menunggu Konfirmasi',
            'confirmed' => 'Terkonfirmasi',
            'failed' => 'Gagal',
            'refunded' => 'Dikembalikan',
        ];

        return $statuses[$status] ?? $status;
    }

    /**
     * Get payment instructions for specific payment
     */
    private function getPaymentInstructions(Payment $payment): array
    {
        $method = $payment->paymentMethod;
        
        if ($method->code === 'cash') {
            return [
                'Bayar tunai di kasir saat mengambil pesanan',
                'Tidak perlu upload bukti pembayaran',
                'Pembayaran otomatis terkonfirmasi',
            ];
        }

        return [
            'Upload bukti pembayaran maksimal 24 jam',
            'Pastikan bukti jelas terbaca',
            'Nomor referensi: ' . ($payment->reference_number ?? '-'),
            'Status saat ini: ' . $this->getFormattedStatus($payment->status),
        ];
    }

    /**
     * Get next possible actions for payment
     */
    private function getNextActions(Payment $payment): array
    {
        $actions = [];

        if ($payment->status === 'pending') {
            $actions[] = [
                'action' => 'upload_proof',
                'label' => 'Upload Bukti Pembayaran',
                'description' => 'Upload bukti transfer/pembayaran',
                'icon' => '📎',
                'method' => 'POST',
                'url' => "/api/customer/payments/{$payment->id}/upload-proof",
            ];
        }

        if ($payment->status === 'waiting_confirmation') {
            $actions[] = [
                'action' => 'resend_notification',
                'label' => 'Kirim Ulang Notifikasi',
                'description' => 'Ingatkan admin untuk verifikasi',
                'icon' => '🔔',
                'method' => 'POST',
                'url' => "/api/customer/payments/{$payment->id}/resend-notification",
            ];
        }

        if (in_array($payment->status, ['pending', 'waiting_confirmation'])) {
            $actions[] = [
                'action' => 'view_instructions',
                'label' => 'Lihat Instruksi',
                'description' => 'Cara melakukan pembayaran',
                'icon' => '📋',
                'method' => 'GET',
                'url' => "/api/customer/payments/{$payment->id}/instructions",
            ];
        }

        return $actions;
    }

    /**
     * Generate detailed payment instructions
     */
    private function generateDetailedInstructions(Payment $payment): array
    {
        $method = $payment->paymentMethod;
        $steps = [];
        $notes = [];

        switch ($method->code) {
            case 'bank_transfer':
                $steps = [
                    "Transfer ke rekening: {$method->name}",
                    "No. Rekening: {$method->account_number}",
                    "Atas Nama: {$method->account_name}",
                    "Jumlah: Rp " . number_format($payment->amount, 0, ',', '.'),
                    "Upload bukti transfer setelah selesai",
                ];
                $notes = [
                    'Pastikan jumlah transfer sesuai',
                    'Simpan bukti transfer asli',
                    'Waktu verifikasi: 1-2 jam kerja',
                ];
                break;

            case 'ewallet':
                $steps = [
                    "Buka aplikasi {$method->name}",
                    "Transfer ke: {$method->account_number}",
                    "Atas Nama: {$method->account_name}",
                    "Screenshot bukti pembayaran",
                    "Upload screenshot",
                ];
                $notes = [
                    'Screenshot harus jelas terbaca',
                    'Tunjukkan nominal dan waktu transfer',
                    'Verifikasi otomatis untuk beberapa e-wallet',
                ];
                break;

            case 'cash':
                $steps = [
                    "Datang ke restoran Chingu Bite",
                    "Tunjukkan nomor pesanan: {$payment->order->order_number}",
                    "Bayar tunai di kasir",
                    "Terima struk pembayaran",
                ];
                $notes = [
                    'Tunai hanya diterima di tempat',
                    'Siapkan uang pas jika memungkinkan',
                    'Pembayaran langsung terkonfirmasi',
                ];
                break;

            default:
                $steps = ['Silakan hubungi kasir untuk instruksi detail'];
                $notes = ['Hubungi 0812-3456-7890 jika ada kendala'];
        }

        return [
            'steps' => $steps,
            'notes' => $notes,
        ];
    }
}