<?php
namespace App\Http\Controllers\Api\Employee;

use App\Http\Controllers\Controller;
use App\Http\Requests\Api\Employee\ConfirmPaymentRequest;
use App\Http\Requests\Api\Employee\FilterPaymentsRequest;
use App\Http\Resources\Api\Employee\PaymentResource;
use App\Models\Payment;
use App\Models\Order;
use App\Traits\ApiResponse;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;

class PaymentConfirmationController extends Controller
{
    use ApiResponse;

    /**
     * Get payments with filters
     * GET /api/employee/payments
     */
    public function index(FilterPaymentsRequest $request): JsonResponse
    {
        try {
            $validated = $request->validated();
            
            $payments = Payment::with(['order.customer', 'paymentMethod', 'confirmedBy'])
                ->when($validated['status'] ?? null, function ($query, $status) {
                    return $query->where('status', $status);
                })
                ->when($validated['payment_method_id'] ?? null, function ($query, $methodId) {
                    return $query->where('payment_method_id', $methodId);
                })
                ->when($validated['date_from'] ?? null, function ($query) use ($validated) {
                    return $query->whereDate('created_at', '>=', $validated['date_from']);
                })
                ->when($validated['date_to'] ?? null, function ($query) use ($validated) {
                    return $query->whereDate('created_at', '<=', $validated['date_to']);
                })
                ->when($validated['search'] ?? null, function ($query, $search) {
                    return $query->where(function ($q) use ($search) {
                        $q->where('reference_number', 'like', "%{$search}%")
                          ->orWhereHas('order', function ($q2) use ($search) {
                              $q2->where('order_number', 'like', "%{$search}%")
                                 ->orWhereHas('customer', function ($q3) use ($search) {
                                     $q3->where('name', 'like', "%{$search}%")
                                        ->orWhere('phone', 'like', "%{$search}%");
                                 });
                          });
                    });
                })
                ->orderBy('created_at', 'desc')
                ->paginate($validated['per_page'] ?? 20);

            // Statistics
            $stats = [
                'total_payments' => $payments->total(),
                'total_amount' => Payment::when($validated['status'] ?? null, function ($query, $status) {
                                        return $query->where('status', $status);
                                    })
                                    ->when($validated['date_from'] ?? null, function ($query) use ($validated) {
                                        return $query->whereDate('created_at', '>=', $validated['date_from']);
                                    })
                                    ->when($validated['date_to'] ?? null, function ($query) use ($validated) {
                                        return $query->whereDate('created_at', '<=', $validated['date_to']);
                                    })
                                    ->sum('amount'),
                'waiting_confirmation' => Payment::where('status', 'waiting_confirmation')
                                               ->when($validated['date_from'] ?? null, function ($query) use ($validated) {
                                                   return $query->whereDate('created_at', '>=', $validated['date_from']);
                                               })
                                               ->when($validated['date_to'] ?? null, function ($query) use ($validated) {
                                                   return $query->whereDate('created_at', '<=', $validated['date_to']);
                                               })
                                               ->count(),
                'overdue_payments' => Payment::where('status', 'waiting_confirmation')
                                           ->where('created_at', '<', now()->subHours(24))
                                           ->count(),
            ];

            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' => $validated,
            ], 'Daftar pembayaran berhasil diambil');

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

    /**
     * Get payment detail
     * GET /api/employee/payments/{id}
     */
    public function show($id): JsonResponse
    {
        try {
            $payment = Payment::with([
                'order.customer',
                'paymentMethod',
                'confirmedBy:id,name'
            ])->find($id);

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

            return $this->successResponse(
                new PaymentResource($payment),
                'Detail pembayaran berhasil diambil'
            );

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

    /**
     * Confirm payment
     * POST /api/employee/payments/{id}/confirm
     */
    public function confirm(ConfirmPaymentRequest $request, $id): JsonResponse
    {
        DB::beginTransaction();
        
        try {
            $payment = Payment::with(['order'])->find($id);
            
            if (!$payment) {
                return $this->errorResponse('Pembayaran tidak ditemukan', 404);
            }

            if ($payment->status !== 'waiting_confirmation') {
                return $this->errorResponse(
                    "Pembayaran sudah dalam status: {$payment->getFormattedStatus()}",
                    400
                );
            }

            $employee = $request->user();
            $validated = $request->validated();

            // Update payment
            $payment->update([
                'status' => 'confirmed',
                'confirmed_by' => $employee->id,
                'confirmed_at' => now(),
                'notes' => $validated['notes'] ?? $payment->notes,
            ]);

            // Update order status if still pending/confirmed
            if (in_array($payment->order->status, ['pending', 'confirmed'])) {
                $payment->order->update([
                    'status' => 'preparing',
                    'employee_id' => $employee->id,
                ]);
            }

            DB::commit();

            return $this->successResponse(
                new PaymentResource($payment->fresh(['order.customer', 'confirmedBy'])),
                '✅ Pembayaran berhasil dikonfirmasi. Pesanan dipindahkan ke status "Sedang Disiapkan".'
            );

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

    /**
     * Reject payment
     * POST /api/employee/payments/{id}/reject
     */
    public function reject(Request $request, $id): JsonResponse
    {
        $request->validate([
            'reason' => 'required|string|max:500',
        ]);

        DB::beginTransaction();
        
        try {
            $payment = Payment::with(['order'])->find($id);
            
            if (!$payment) {
                return $this->errorResponse('Pembayaran tidak ditemukan', 404);
            }

            if ($payment->status !== 'waiting_confirmation') {
                return $this->errorResponse(
                    "Pembayaran sudah dalam status: {$payment->getFormattedStatus()}",
                    400
                );
            }

            $employee = $request->user();

            // Update payment
            $payment->update([
                'status' => 'failed',
                'confirmed_by' => $employee->id,
                'confirmed_at' => now(),
                'notes' => ($payment->notes ?? '') . "\n[Ditolak: " . $request->reason . " - oleh " . $employee->name . "]",
            ]);

            // Update order status back to pending if it was confirmed
            if ($payment->order->status === 'confirmed') {
                $payment->order->update([
                    'status' => 'pending',
                    'notes' => ($payment->order->notes ?? '') . "\n[Pembayaran ditolak: " . $request->reason . "]",
                ]);
            }

            DB::commit();

            return $this->successResponse(
                new PaymentResource($payment->fresh(['order.customer', 'confirmedBy'])),
                '❌ Pembayaran ditolak. Customer akan diminta untuk mengupload bukti baru.'
            );

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

    /**
     * Get payments waiting for confirmation
     * GET /api/employee/payments/waiting-confirmation
     */
    public function waitingConfirmation(Request $request): JsonResponse
    {
        try {
            $payments = Payment::with(['order.customer', 'paymentMethod'])
                ->where('status', 'waiting_confirmation')
                ->orderBy('created_at', 'asc') // Oldest first
                ->paginate($request->per_page ?? 20);

            // Check for overdue payments
            $overduePayments = Payment::where('status', 'waiting_confirmation')
                                    ->where('created_at', '<', now()->subHours(24))
                                    ->count();

            return $this->successResponse([
                'payments' => PaymentResource::collection($payments),
                'pagination' => [
                    'total' => $payments->total(),
                    'per_page' => $payments->perPage(),
                    'current_page' => $payments->currentPage(),
                    'last_page' => $payments->lastPage(),
                ],
                'summary' => [
                    'total_waiting' => $payments->total(),
                    'overdue_count' => $overduePayments,
                    'average_wait_time' => $this->calculateAverageWaitTime(),
                ],
                'instructions' => [
                    'Periksa bukti transfer dengan cermat',
                    'Pastikan nominal sesuai dengan pesanan',
                    'Verifikasi keaslian bukti transfer',
                    'Prioritaskan pembayaran yang sudah lama menunggu',
                ]
            ], 'Pembayaran menunggu konfirmasi berhasil diambil');

        } catch (\Exception $e) {
            return $this->errorResponse('Gagal mengambil pembayaran menunggu konfirmasi: ' . $e->getMessage(), 500);
        }
    }

    /**
     * Get payment statistics
     * GET /api/employee/payments/statistics
     */
    public function statistics(Request $request): JsonResponse
    {
        try {
            $validated = $request->validate([
                'period' => 'nullable|in:today,week,month,year',
                'date_from' => 'nullable|date',
                'date_to' => 'nullable|date',
            ]);

            $period = $validated['period'] ?? 'today';
            
            // Determine date range
            switch ($period) {
                case 'week':
                    $startDate = now()->startOfWeek()->format('Y-m-d');
                    $endDate = now()->endOfWeek()->format('Y-m-d');
                    break;
                case 'month':
                    $startDate = now()->startOfMonth()->format('Y-m-d');
                    $endDate = now()->endOfMonth()->format('Y-m-d');
                    break;
                case 'year':
                    $startDate = now()->startOfYear()->format('Y-m-d');
                    $endDate = now()->endOfYear()->format('Y-m-d');
                    break;
                default: // today
                    $startDate = now()->format('Y-m-d');
                    $endDate = now()->format('Y-m-d');
            }

            // Override with custom dates if provided
            if ($validated['date_from'] ?? null) {
                $startDate = $validated['date_from'];
            }
            if ($validated['date_to'] ?? null) {
                $endDate = $validated['date_to'];
            }

            // Status distribution
            $statusDistribution = Payment::selectRaw('status, COUNT(*) as count')
                ->whereDate('created_at', '>=', $startDate)
                ->whereDate('created_at', '<=', $endDate)
                ->groupBy('status')
                ->get()
                ->mapWithKeys(function ($item) {
                    return [$item->status => $item->count];
                });

            // Payment method distribution
            $methodDistribution = Payment::selectRaw('payment_methods.name, COUNT(*) as count')
                ->join('payment_methods', 'payments.payment_method_id', '=', 'payment_methods.id')
                ->whereDate('payments.created_at', '>=', $startDate)
                ->whereDate('payments.created_at', '<=', $endDate)
                ->groupBy('payment_methods.name')
                ->get()
                ->mapWithKeys(function ($item) {
                    return [$item->name => $item->count];
                });

            // Daily confirmed payments
            $dailyConfirmed = Payment::selectRaw('DATE(created_at) as date, SUM(amount) as total')
                ->where('status', 'confirmed')
                ->whereDate('created_at', '>=', $startDate)
                ->whereDate('created_at', '<=', $endDate)
                ->groupBy('date')
                ->orderBy('date')
                ->get()
                ->map(function ($item) {
                    return [
                        'date' => $item->date,
                        'total' => (float) $item->total,
                    ];
                });

            // Confirmation time statistics
            $confirmationTimes = Payment::where('status', 'confirmed')
                ->whereNotNull('confirmed_at')
                ->whereDate('created_at', '>=', $startDate)
                ->whereDate('created_at', '<=', $endDate)
                ->get()
                ->map(function ($payment) {
                    return $payment->created_at->diffInMinutes($payment->confirmed_at);
                });

            $avgConfirmationTime = $confirmationTimes->isNotEmpty() 
                ? round($confirmationTimes->avg(), 1) 
                : 0;

            return $this->successResponse([
                'period' => [
                    'start_date' => $startDate,
                    'end_date' => $endDate,
                    'period_name' => $period,
                ],
                'totals' => [
                    'total_payments' => Payment::whereDate('created_at', '>=', $startDate)
                                             ->whereDate('created_at', '<=', $endDate)
                                             ->count(),
                    'total_confirmed' => Payment::where('status', 'confirmed')
                                              ->whereDate('created_at', '>=', $startDate)
                                              ->whereDate('created_at', '<=', $endDate)
                                              ->sum('amount'),
                    'pending_confirmation' => Payment::where('status', 'waiting_confirmation')
                                                   ->whereDate('created_at', '>=', $startDate)
                                                   ->whereDate('created_at', '<=', $endDate)
                                                   ->count(),
                ],
                'status_distribution' => $statusDistribution,
                'method_distribution' => $methodDistribution,
                'daily_confirmed' => $dailyConfirmed,
                'performance' => [
                    'avg_confirmation_time_minutes' => $avgConfirmationTime,
                    'confirmation_rate' => Payment::whereDate('created_at', '>=', $startDate)
                                                ->whereDate('created_at', '<=', $endDate)
                                                ->where('status', '!=', 'pending')
                                                ->count() > 0 
                    ? round((Payment::whereDate('created_at', '>=', $startDate)
                                   ->whereDate('created_at', '<=', $endDate)
                                   ->where('status', 'confirmed')
                                   ->count() / Payment::whereDate('created_at', '>=', $startDate)
                                                    ->whereDate('created_at', '<=', $endDate)
                                                    ->where('status', '!=', 'pending')
                                                    ->count()) * 100, 1)
                    : 0,
                ],
            ], 'Statistik pembayaran berhasil diambil');

        } catch (\Exception $e) {
            return $this->errorResponse('Gagal mengambil statistik: ' . $e->getMessage(), 500);
        }
    }

    /**
     * Get overdue payments
     * GET /api/employee/payments/overdue
     */
    public function overduePayments(Request $request): JsonResponse
    {
        try {
            $overduePayments = Payment::with(['order.customer', 'paymentMethod'])
                ->where('status', 'waiting_confirmation')
                ->where('created_at', '<', now()->subHours(24))
                ->orderBy('created_at', 'asc')
                ->get();

            return $this->successResponse([
                'payments' => PaymentResource::collection($overduePayments),
                'count' => $overduePayments->count(),
                'oldest_waiting' => $overduePayments->isNotEmpty() 
                    ? $overduePayments->first()->created_at->diffForHumans()
                    : null,
                'actions' => [
                    'contact_customer' => 'Hubungi customer untuk konfirmasi',
                    'auto_reject' => 'Otomatis tolak setelah 48 jam',
                    'extend_time' => 'Perpanjang waktu konfirmasi',
                ]
            ], 'Pembayaran overdue berhasil diambil');

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

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

    /**
     * Calculate average wait time for confirmation
     */
    private function calculateAverageWaitTime(): string
    {
        $payments = Payment::where('status', 'waiting_confirmation')
                          ->get();

        if ($payments->isEmpty()) {
            return '0 menit';
        }

        $totalMinutes = $payments->sum(function ($payment) {
            return $payment->created_at->diffInMinutes(now());
        });

        $averageMinutes = $totalMinutes / $payments->count();
        
        if ($averageMinutes < 60) {
            return round($averageMinutes) . ' menit';
        } else {
            $hours = floor($averageMinutes / 60);
            $minutes = round($averageMinutes % 60);
            return $hours . ' jam ' . $minutes . ' menit';
        }
    }
}