<?php

namespace App\Http\Controllers;

use App\Models\Customer;
use App\Models\Order;
use App\Models\OrderStatus;
use App\Models\OrderStatusHistory;
use App\Models\Setting;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;

class OrderController extends Controller
{
    /**
     * Display the admin dashboard page.
     */
    public function adminDashboard()
    {
        return view('admin.dashboard');
    }

    /**
     * Get list of all orders, formatted for the frontend.
     */
    public function index()
    {
        $orders = Order::with(['customer', 'status', 'courier'])
            ->orderBy('created_at', 'desc')
            ->get()
            ->map(function ($order) {
                return [
                    'id' => $order->id,
                    'nomor' => $order->receipt_number,
                    'nama' => $order->customer ? $order->customer->name : 'Unknown',
                    'phone' => $order->customer ? $order->customer->phone : null,
                    'customer_id' => $order->customer_id,
                    'status' => $order->status ? $order->status->status_name : 'jemput',
                    'status_id' => $order->status_id,
                    'note' => $order->note,
                    'jarak' => $order->distance,
                    'cost' => $order->shipping_cost,
                    'date' => $order->order_date
                        ? $order->order_date->format('d/m/Y, H.i.s')
                        : $order->created_at->format('d/m/Y, H.i.s'),
                    'processStage' => $order->process_stage,
                    'courier_id' => $order->courier_id,
                    'courier_name' => $order->courier ? $order->courier->name : null,
                    'courier_phone' => $order->courier ? $order->courier->phone : null,
                ];
            });

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

    /**
     * Display printable receipt for an order.
     */
    public function receipt($id)
    {
        $order = Order::with(['customer', 'status', 'courier'])->findOrFail($id);
        $trackingUrl = url('/?resi=' . urlencode($order->receipt_number));
        return view('admin.receipt', compact('order', 'trackingUrl'));
    }

    /**
     * Generate the next receipt number in format OKL-YYYYMMDD-xxx.
     */
    public function generateReceipt()
    {
        $prefix = 'OKL-' . now()->format('Ymd') . '-';

        $lastToday = Order::where('receipt_number', 'like', $prefix . '%')
            ->orderBy('receipt_number', 'desc')
            ->first();

        $nextSeq = 1;
        if ($lastToday) {
            $lastSeq = (int) substr($lastToday->receipt_number, strlen($prefix));
            $nextSeq = $lastSeq + 1;
        }

        $receipt = $prefix . str_pad($nextSeq, 3, '0', STR_PAD_LEFT);

        return response()->json(['receipt_number' => $receipt]);
    }

    /**
     * Calculate Haversine distance between two coordinates in km.
     */
    private function haversine($lat1, $lon1, $lat2, $lon2)
    {
        $earthRadius = 6371; // km
        $dLat = deg2rad($lat2 - $lat1);
        $dLon = deg2rad($lon2 - $lon1);
        $a = sin($dLat / 2) * sin($dLat / 2) +
             cos(deg2rad($lat1)) * cos(deg2rad($lat2)) *
             sin($dLon / 2) * sin($dLon / 2);
        $c = 2 * asin(sqrt($a));
        return $earthRadius * $c;
    }

    /**
     * Calculate shipping cost based on distance using mitra settings.
     */
    private function calculateShippingCost($distance)
    {
        $mitra = Setting::mitra();
        $free = $mitra['free_radius_km'];
        return $distance <= $free ? 0 : round(($distance - $free) * $mitra['cost_per_km']);
    }

    /**
     * Store a new order or update an existing one.
     */
    public function store(Request $request)
    {
        $validated = $request->validate([
            'receipt_number' => ['required', 'string', 'max:255'],
            'customer_id' => ['required', 'exists:customers,id'],
            'status_name' => ['required', 'string', 'in:jemput,proses,antar,selesai,ditolak'],
            'note' => ['nullable', 'string', 'max:1000'],
            'process_stage' => ['nullable', 'string', 'in:cuci,kering,setrika'],
            'distance_input' => ['nullable', 'numeric', 'min:0', 'max:100'],
            'courier_id' => ['nullable', 'exists:couriers,id'],
        ]);

        $customer = Customer::findOrFail($validated['customer_id']);
        $status = OrderStatus::where('status_name', $validated['status_name'])->firstOrFail();

        // Calculate distance via Haversine if coordinate is set, otherwise use input or default
        if ($customer->latitude && $customer->longitude) {
            $mitra = Setting::mitra();
            $distVal = $this->haversine($mitra['lat'], $mitra['lng'], $customer->latitude, $customer->longitude);
            $distance = round($distVal);
        } elseif (!empty($validated['distance_input'])) {
            $distance = round($validated['distance_input']);
        } else {
            $distance = 0;
        }

        $shippingCost = $this->calculateShippingCost($distance);

        // Determine process stage
        $processStage = $validated['status_name'] === 'proses'
            ? ($validated['process_stage'] ?? null)
            : null;

        // Find existing order by receipt number or create new
        $order = Order::where('receipt_number', $validated['receipt_number'])->first();

        $orderData = [
            'customer_id' => $customer->id,
            'status_id' => $status->id,
            'user_id' => Auth::id(),
            'courier_id' => $validated['courier_id'] ?? null,
            'distance' => $distance,
            'shipping_cost' => $shippingCost,
            'note' => $validated['note'] ?? null,
            'process_stage' => $processStage,
        ];

        if ($order) {
            $statusChanged = $order->status_id !== $status->id || $order->process_stage !== $processStage;
            $order->update($orderData);
            if ($statusChanged) {
                OrderStatusHistory::create([
                    'order_id' => $order->id,
                    'status_name' => $status->status_name,
                    'process_stage' => $processStage,
                ]);
            }
        } else {
            $order = Order::create(array_merge($orderData, [
                'receipt_number' => $validated['receipt_number'],
                'order_date' => now(),
            ]));
            OrderStatusHistory::create([
                'order_id' => $order->id,
                'status_name' => $status->status_name,
                'process_stage' => $processStage,
            ]);
        }

        return $this->index();
    }

    /**
     * Delete an order.
     */
    public function destroy($id)
    {
        $order = Order::findOrFail($id);
        $order->delete();

        return $this->index();
    }
}
