<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Purchase;
use App\Models\PurchaseTracking;
use App\Models\User;
use App\Notifications\PurchaseStatusNotification;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class SupplierOrderController extends Controller
{
    /**
     * GET /api/supplier-portal/orders
     * List all purchases assigned to the logged-in supplier.
     */
    public function index(Request $request)
    {
        $supplier = $request->user()->supplier;

        if (!$supplier) {
            return response()->json(['message' => 'Akun supplier tidak ditemukan.'], 403);
        }

        $orders = Purchase::with(['user:id,name', 'items', 'warehouse:id,code,name', 'trackings.actor:id,name'])
            ->where('supplier_id', $supplier->id)
            ->whereNotIn('status', ['draft']) // Supplier only sees sent+ orders
            ->when($request->status, fn($q) => $q->where('status', $request->status))
            ->when($request->search, fn($q) => $q->where('po_number', 'like', "%{$request->search}%"))
            ->latest()
            ->paginate(20);

        return response()->json($orders->through(fn($p) => $this->format($p)));
    }

    /**
     * GET /api/supplier-portal/orders/{purchase}
     */
    public function show(Request $request, Purchase $purchase)
    {
        $supplier = $request->user()->supplier;

        if (!$supplier || $purchase->supplier_id !== $supplier->id) {
            return response()->json(['message' => 'Pesanan tidak ditemukan.'], 404);
        }

        $purchase->load(['user:id,name', 'items', 'warehouse:id,code,name', 'trackings.actor:id,name']);

        return response()->json($this->format($purchase));
    }

    /**
     * PATCH /api/supplier-portal/orders/{purchase}/confirm
     * Supplier confirms the order (sent → confirmed).
     */
    public function confirm(Request $request, Purchase $purchase)
    {
        $supplier = $request->user()->supplier;

        if (!$supplier || $purchase->supplier_id !== $supplier->id) {
            return response()->json(['message' => 'Pesanan tidak ditemukan.'], 404);
        }

        if ($purchase->status !== 'sent') {
            return response()->json(['message' => 'Pesanan hanya bisa dikonfirmasi dari status "Dikirim".'], 422);
        }

        return DB::transaction(function () use ($purchase, $request) {
            $purchase->update(['status' => 'confirmed']);

            PurchaseTracking::create([
                'purchase_id' => $purchase->id,
                'status'      => 'confirmed',
                'description' => 'Pesanan dikonfirmasi oleh supplier',
                'actor_id'    => $request->user()->id,
                'actor_role'  => 'supplier',
            ]);

            // Notify warehouse users (manager + super_admin)
            $this->notifyWarehouseUsers($purchase, 'confirmed',
                "PO #{$purchase->po_number} telah dikonfirmasi oleh supplier.",
                $request->user()->name
            );

            return response()->json($this->format($purchase->fresh()->load(['user', 'items', 'warehouse', 'trackings.actor'])));
        });
    }

    /**
     * PATCH /api/supplier-portal/orders/{purchase}/process
     * Supplier starts processing (confirmed → processing).
     */
    public function process(Request $request, Purchase $purchase)
    {
        $supplier = $request->user()->supplier;

        if (!$supplier || $purchase->supplier_id !== $supplier->id) {
            return response()->json(['message' => 'Pesanan tidak ditemukan.'], 404);
        }

        if ($purchase->status !== 'confirmed') {
            return response()->json(['message' => 'Pesanan hanya bisa diproses dari status "Dikonfirmasi".'], 422);
        }

        return DB::transaction(function () use ($purchase, $request) {
            $purchase->update(['status' => 'processing']);

            PurchaseTracking::create([
                'purchase_id' => $purchase->id,
                'status'      => 'processing',
                'description' => 'Pesanan sedang diproses oleh supplier',
                'actor_id'    => $request->user()->id,
                'actor_role'  => 'supplier',
            ]);

            $this->notifyWarehouseUsers($purchase, 'processing',
                "PO #{$purchase->po_number} sedang diproses oleh supplier.",
                $request->user()->name
            );

            return response()->json($this->format($purchase->fresh()->load(['user', 'items', 'warehouse', 'trackings.actor'])));
        });
    }

    /**
     * PATCH /api/supplier-portal/orders/{purchase}/ship
     * Supplier ships the order (processing → shipped).
     */
    public function ship(Request $request, Purchase $purchase)
    {
        $supplier = $request->user()->supplier;

        if (!$supplier || $purchase->supplier_id !== $supplier->id) {
            return response()->json(['message' => 'Pesanan tidak ditemukan.'], 404);
        }

        if (!in_array($purchase->status, ['confirmed', 'processing'])) {
            return response()->json(['message' => 'Pesanan hanya bisa dikirim dari status "Dikonfirmasi" atau "Diproses".'], 422);
        }

        $data = $request->validate([
            'notes'       => ['nullable', 'string'],
            'driver_name' => ['nullable', 'string', 'max:100'],
        ]);

        return DB::transaction(function () use ($purchase, $request, $data) {
            $purchase->update(['status' => 'shipped']);

            // Auto-generate surat jalan number (SJ-IN-YYYYMMDD-NNN)
            $today = now()->format('Ymd');
            $prefix = "SJ-IN-{$today}-";
            $prefixLen = strlen($prefix) + 1;

            // Get last number for today from stock_movements AND purchase_trackings
            $lastFromMovements = \App\Models\StockMovement::where('reference_no', 'like', "{$prefix}%")
                ->whereRaw("LENGTH(SUBSTRING(reference_no, ?)) <= 4", [$prefixLen])
                ->selectRaw("MAX(CAST(SUBSTRING(reference_no, ?) AS UNSIGNED)) as max_num", [$prefixLen])
                ->value('max_num') ?? 0;

            $lastFromTrackings = PurchaseTracking::where('tracking_number', 'like', "{$prefix}%")
                ->whereRaw("LENGTH(SUBSTRING(tracking_number, ?)) <= 4", [$prefixLen])
                ->selectRaw("MAX(CAST(SUBSTRING(tracking_number, ?) AS UNSIGNED)) as max_num", [$prefixLen])
                ->value('max_num') ?? 0;

            $nextNum = max($lastFromMovements, $lastFromTrackings) + 1;
            $suratJalan = $prefix . str_pad($nextNum, 3, '0', STR_PAD_LEFT);

            $description = "Barang telah dikirim oleh supplier (Surat Jalan: {$suratJalan})";

            PurchaseTracking::create([
                'purchase_id'     => $purchase->id,
                'status'          => 'shipped',
                'description'     => $description,
                'actor_id'        => $request->user()->id,
                'actor_role'      => 'supplier',
                'tracking_number' => $suratJalan,
                'driver_name'     => $data['driver_name'] ?? null,
            ]);

            $driverName = $data['driver_name'] ?? null;
            $message = $driverName
                ? "PO #{$purchase->po_number} telah dikirim oleh driver {$driverName}. Surat Jalan: {$suratJalan}"
                : "PO #{$purchase->po_number} telah dikirim. Surat Jalan: {$suratJalan}";

            $this->notifyWarehouseUsers($purchase, 'shipped', $message, $request->user()->name);

            return response()->json($this->format($purchase->fresh()->load(['user', 'items', 'warehouse', 'trackings.actor'])));
        });
    }

    /**
     * Notify all manager and super_admin users about PO status changes.
     */
    private function notifyWarehouseUsers(Purchase $purchase, string $status, string $message, ?string $actorName): void
    {
        $users = User::whereHas('roles', function ($q) {
            $q->whereIn('name', ['manager', 'super_admin']);
        })->get();

        foreach ($users as $user) {
            $user->notify(new PurchaseStatusNotification($purchase, $status, $message, $actorName));
        }
    }

    private function format(Purchase $purchase): array
    {
        return [
            'id'             => $purchase->id,
            'po_number'      => $purchase->po_number,
            'supplier_name'  => $purchase->supplier?->name ?? $purchase->supplier_name,
            'operator_name'  => $purchase->user?->name ?? 'Unknown',
            'warehouse_id'   => $purchase->warehouse_id,
            'warehouse_name' => $purchase->warehouse?->name ?? '-',
            'status'         => $purchase->status,
            'items'          => $purchase->items->map(fn($i) => [
                'id'           => $i->id,
                'product_id'   => $i->product_id,
                'sku'          => $i->sku,
                'product_name' => $i->product_name,
                'qty_ordered'  => $i->qty_ordered,
                'qty_received' => $i->qty_received,
                'unit_price'   => $i->unit_price,
                'subtotal'     => $i->subtotal,
            ]),
            'trackings' => $purchase->trackings->map(fn($t) => [
                'id'              => $t->id,
                'status'          => $t->status,
                'description'     => $t->description,
                'actor_name'      => $t->actor?->name ?? 'System',
                'actor_role'      => $t->actor_role,
                'tracking_number' => $t->tracking_number,
                'driver_name'     => $t->driver_name,
                'created_at'      => $t->created_at->toISOString(),
            ]),
            'total'          => $purchase->total,
            'notes'          => $purchase->notes,
            'expected_date'  => $purchase->expected_date?->toDateString(),
            'created_at'     => $purchase->created_at->toISOString(),
            'received_at'    => $purchase->received_at?->toISOString(),
        ];
    }
}
