<?php

namespace App\Http\Controllers;

use App\Models\Order;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\Rule;

class InvoiceController extends Controller
{
    /**
     * Display the invoice for a specific order
     *
     * @param Order $order
     * @return \Illuminate\View\View
     */
    public function show(Order $order)
    {
        $this->authorize('view', $order);

        // Load necessary relationships
        $order->load(['store', 'logs.user']);

        return view('orders.invoice', compact('order'));
    }

    /**
     * Display print-optimized invoice view
     *
     * @param Order $order
     * @return \Illuminate\View\View
     */
    public function print(Order $order)
    {
        $this->authorize('view', $order);

        $order->load(['store', 'logs.user']);

        return view('orders.invoice-print', compact('order'))
            ->with('printMode', true);
    }

    /**
     * Download invoice as PDF
     *
     * @param Order $order
     * @return \Illuminate\Http\Response
     */
    public function download(Order $order)
    {
        $this->authorize('view', $order);

        try {
            $order->load(['store', 'logs.user']);

            // Generate PDF using DomPDF or similar
            $pdf = app('dompdf.wrapper');
            $pdf->loadView('orders.invoice-pdf', compact('order'));
            $pdf->setPaper('A4', 'portrait');

            $filename = 'invoice-' . $order->order_number . '.pdf';

            return $pdf->download($filename);

        } catch (\Exception $e) {
            Log::error('Invoice PDF generation failed', [
                'order_id' => $order->id,
                'error' => $e->getMessage()
            ]);

            return redirect()->back()
                ->with('error', 'Failed to generate PDF. Please try again.');
        }
    }

    /**
     * Update order status
     *
     * @param Request $request
     * @param Order $order
     * @return \Illuminate\Http\JsonResponse
     */
    public function updateStatus(Request $request, Order $order)
    {
        $this->authorize('update', $order);

        $request->validate([
            'status' => ['required', Rule::in([
                'processing', 'completed', 'pending', 'on-hold', 
                'cancelled', 'refunded', 'failed'
            ])]
        ]);

        $oldStatus = $order->status;
        $newStatus = $request->input('status');

        try {
            $order->update(['status' => $newStatus]);

            // Log the status change
            $order->logs()->create([
                'user_id' => auth()->id(),
                'action' => "Status changed from {$oldStatus} to {$newStatus}",
                'metadata' => [
                    'old_status' => $oldStatus,
                    'new_status' => $newStatus,
                    'changed_at' => now(),
                ]
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Order status updated successfully',
                'new_status' => $newStatus
            ]);

        } catch (\Exception $e) {
            Log::error('Status update failed', [
                'order_id' => $order->id,
                'error' => $e->getMessage()
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Failed to update status'
            ], 500);
        }
    }

    /**
     * Update payment status
     *
     * @param Request $request
     * @param Order $order
     * @return \Illuminate\Http\JsonResponse
     */
    public function updatePaymentStatus(Request $request, Order $order)
    {
        $this->authorize('update', $order);

        $request->validate([
            'payment_status' => ['required', 'string', 'max:50']
        ]);

        try {
            $order->update([
                'payment_status' => $request->input('payment_status')
            ]);

            $order->logs()->create([
                'user_id' => auth()->id(),
                'action' => "Payment status updated to {$request->input('payment_status')}",
                'metadata' => [
                    'payment_status' => $request->input('payment_status'),
                    'updated_at' => now(),
                ]
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Payment status updated successfully'
            ]);

        } catch (\Exception $e) {
            Log::error('Payment status update failed', [
                'order_id' => $order->id,
                'error' => $e->getMessage()
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Failed to update payment status'
            ], 500);
        }
    }

    /**
     * Update tracking information
     *
     * @param Request $request
     * @param Order $order
     * @return \Illuminate\Http\JsonResponse
     */
    public function updateTracking(Request $request, Order $order)
    {
        $this->authorize('update', $order);

        $request->validate([
            'tracking_number' => ['nullable', 'string', 'max:100'],
            'courier' => ['nullable', 'string', 'max:100'],
            'shipping_notes' => ['nullable', 'string', 'max:500']
        ]);

        try {
            $order->update([
                'tracking_number' => $request->input('tracking_number'),
                'courier' => $request->input('courier'),
                'shipping_notes' => $request->input('shipping_notes'),
            ]);

            $order->logs()->create([
                'user_id' => auth()->id(),
                'action' => 'Tracking information updated',
                'metadata' => [
                    'tracking_number' => $request->input('tracking_number'),
                    'courier' => $request->input('courier'),
                    'updated_at' => now(),
                ]
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Tracking information updated successfully'
            ]);

        } catch (\Exception $e) {
            Log::error('Tracking update failed', [
                'order_id' => $order->id,
                'error' => $e->getMessage()
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Failed to update tracking information'
            ], 500);
        }
    }

    /**
     * Preview invoice with different template
     *
     * @param Order $order
     * @param string $template
     * @return \Illuminate\View\View
     */
    public function preview(Order $order, $template = 'default')
    {
        $this->authorize('view', $order);

        $order->load(['store', 'logs.user']);

        $templateMap = [
            'default' => 'orders.invoice',
            'minimal' => 'orders.invoice-minimal',
            'detailed' => 'orders.invoice-detailed',
            'compact' => 'orders.invoice-compact'
        ];

        $viewName = $templateMap[$template] ?? $templateMap['default'];

        if (!View::exists($viewName)) {
            $viewName = $templateMap['default'];
        }

        return view($viewName, compact('order', 'template'));
    }

    /**
     * Public invoice view (for customers)
     *
     * @param Order $order
     * @param string $token
     * @return \Illuminate\View\View
     */
    public function publicView(Order $order, $token)
    {
        // Verify token/hash for security
        $expectedToken = hash('sha256', $order->id . $order->created_at . config('app.key'));
        
        if (!hash_equals($expectedToken, $token)) {
            abort(403, 'Invalid access token');
        }

        $order->load(['store']);

        return view('orders.invoice-public', compact('order'))
            ->with('hideControls', true);
    }

    /**
     * Get status options for dropdowns
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function getStatusOptions()
    {
        $statuses = [
            'processing' => ['label' => 'Processing', 'color' => 'status-warning'],
            'completed' => ['label' => 'Completed', 'color' => 'status-success'],
            'pending' => ['label' => 'Pending', 'color' => 'status-secondary'],
            'on-hold' => ['label' => 'On Hold', 'color' => 'status-warning'],
            'cancelled' => ['label' => 'Cancelled', 'color' => 'status-danger'],
            'refunded' => ['label' => 'Refunded', 'color' => 'status-info'],
            'failed' => ['label' => 'Failed', 'color' => 'status-danger'],
        ];

        return response()->json($statuses);
    }

    /**
     * Get payment method options
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function getPaymentMethods()
    {
        $methods = [
            'cod' => ['label' => 'Cash on Delivery', 'color' => 'payment-cod'],
            'bacs' => ['label' => 'Bank Transfer', 'color' => 'payment-bacs'],
            'stripe' => ['label' => 'Stripe', 'color' => 'payment-stripe'],
            'paypal' => ['label' => 'PayPal', 'color' => 'payment-paypal'],
        ];

        return response()->json($methods);
    }

    /**
     * Bulk operations for multiple invoices
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function bulkPrint(Request $request)
    {
        $this->authorize('bulk-manage', Order::class);

        $request->validate([
            'order_ids' => ['required', 'array'],
            'order_ids.*' => ['required', 'integer', 'exists:orders,id']
        ]);

        try {
            $orders = Order::whereIn('id', $request->input('order_ids'))
                ->with(['store', 'logs.user'])
                ->get();

            // Generate combined PDF or return print URLs
            $printUrls = $orders->map(function ($order) {
                return route('invoices.print', $order);
            });

            return response()->json([
                'success' => true,
                'message' => 'Print jobs prepared',
                'urls' => $printUrls
            ]);

        } catch (\Exception $e) {
            Log::error('Bulk print failed', [
                'order_ids' => $request->input('order_ids'),
                'error' => $e->getMessage()
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Failed to prepare print jobs'
            ], 500);
        }
    }

    /**
     * Handle webhook for external integrations
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function handleWebhook(Request $request)
    {
        // Verify webhook signature
        $signature = $request->header('X-Webhook-Signature');
        $payload = $request->getContent();
        $expectedSignature = hash_hmac('sha256', $payload, config('invoice.api.webhook_secret'));

        if (!hash_equals($expectedSignature, $signature)) {
            Log::warning('Invalid webhook signature');
            return response()->json(['error' => 'Invalid signature'], 401);
        }

        try {
            $data = $request->json()->all();
            
            if (isset($data['order_id']) && isset($data['status'])) {
                $order = Order::find($data['order_id']);
                
                if ($order) {
                    $order->update(['status' => $data['status']]);
                    
                    $order->logs()->create([
                        'user_id' => null,
                        'action' => 'Status updated via webhook',
                        'metadata' => $data
                    ]);
                }
            }

            return response()->json(['success' => true]);

        } catch (\Exception $e) {
            Log::error('Webhook processing failed', [
                'payload' => $request->all(),
                'error' => $e->getMessage()
            ]);

            return response()->json([
                'error' => 'Processing failed'
            ], 500);
        }
    }

    /**
     * Invoice settings management
     *
     * @return \Illuminate\View\View
     */
    public function settings()
    {
        $this->authorize('manage-settings');

        $currentSettings = config('invoice');

        return view('admin.invoice-settings', compact('currentSettings'));
    }

    /**
     * Update invoice settings
     *
     * @param Request $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function updateSettings(Request $request)
    {
        $this->authorize('manage-settings');

        $request->validate([
            'company.name' => ['required', 'string', 'max:255'],
            'company.address' => ['required', 'string', 'max:500'],
            'defaults.currency' => ['required', 'string', 'max:10'],
            'defaults.country_code' => ['required', 'string', 'max:5'],
        ]);

        try {
            // Update configuration file or database settings
            // This would typically involve updating a settings table
            // or dynamically updating the config file

            return redirect()->back()
                ->with('success', 'Invoice settings updated successfully');

        } catch (\Exception $e) {
            Log::error('Settings update failed', [
                'error' => $e->getMessage()
            ]);

            return redirect()->back()
                ->with('error', 'Failed to update settings');
        }
    }
}
