<?php

namespace App\Http\Controllers;

use App\Models\Invoice;
use App\Models\InvoiceActivityLog;
use App\Models\Customer;
use App\Models\ServiceAsset;
use App\Models\ServiceLog;
use App\Models\ServiceTicket;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\View\View;

class CourierController extends Controller
{
    /**
     * Daftar tiket yang menunggu pickup dari customer.
     * Menampilkan 2 tab: Pickup Requested (baru) dan Pending (lama/walk-in).
     */
    public function pickup(Request $request)
    {
        $search = trim((string) $request->query('search', ''));

        $baseQuery = function ($status) use ($search) {
            return ServiceTicket::where('status', $status)
                ->with('customer')
                ->orderBy('created_at')
                ->when($search !== '', function ($query) use ($search) {
                    $query->where(function ($inner) use ($search) {
                        $inner->where('ticket_code', 'like', "%{$search}%")
                            ->orWhereHas('customer', fn ($c) =>
                                $c->where('name', 'like', "%{$search}%")
                                    ->orWhere('whatsapp', 'like', "%{$search}%")
                            );
                    });
                });
        };

        $pickupRequested = $baseQuery('Pickup Requested')->paginate(20, ['*'], 'req_page')->withQueryString();

        return view('courier.pickup', compact('pickupRequested', 'search'));
    }

    /**
     * Konfirmasi pickup: barang sudah diambil dari customer dan diterima untuk proses teknisi.
     */
    public function confirmPickup(ServiceTicket $ticket)
    {
        if ($ticket->status !== 'Pending') {
            return back()->with('error', 'Pickup hanya bisa diproses untuk tiket berstatus "Pending".');
        }

        $ticket->update([
            'status' => 'Checking',
        ]);

        ServiceLog::create([
            'ticket_id' => $ticket->id,
            'user_id' => auth()->id(),
            'note' => 'Pickup dari customer dikonfirmasi kurir. Status: Checking.',
        ]);

        return back()->with('success', 'Pickup berhasil dikonfirmasi. Tiket masuk antrian teknisi.');
    }

    /**
     * Form untuk kurir mengisi data perangkat lengkap (setelah menjemput dari customer).
     */
    public function showFillData(ServiceTicket $ticket): View|RedirectResponse
    {
        if ($ticket->status !== 'Pickup Requested') {
            return redirect()->route('courier.pickup')
                ->with('error', 'Tiket ini tidak dalam status Pickup Requested.');
        }

        $ticket->load('customer');
        $deviceTypes = ServiceTicket::DEVICE_TYPES;

        return view('courier.fill', compact('ticket', 'deviceTypes'));
    }

    /**
     * Simpan data perangkat lengkap yang diisi kurir; ubah status ke Pending.
     */
    public function saveFillData(Request $request, ServiceTicket $ticket): RedirectResponse
    {
        if ($ticket->status !== 'Pickup Requested') {
            return back()->with('error', 'Tiket ini tidak dalam status Pickup Requested.');
        }

        $validated = $request->validate([
            'device_type'        => ['required', 'in:' . implode(',', ServiceTicket::DEVICE_TYPES)],
            'brand'              => ['required', 'string', 'max:100'],
            'model'              => ['required', 'string', 'max:100'],
            'serial_number'      => ['nullable', 'string', 'max:100'],
            'problem_desc'       => ['required', 'string', 'max:2000'],
            'physical_condition' => ['nullable', 'string', 'max:1000'],
            'device_password'    => ['nullable', 'string', 'max:100'],
            'accessories'        => ['nullable', 'array'],
            'accessories.*'      => ['string', 'max:100'],
            'accessories_other'  => ['nullable', 'string', 'max:255'],
            'photo_entry'        => ['nullable', 'image', 'max:5120'],
            'sig_entry'          => ['nullable', 'string'],
        ]);

        DB::transaction(function () use ($validated, $request, $ticket) {
            $ticket->update([
                'device_type'   => $validated['device_type'],
                'brand'         => $validated['brand'],
                'model'         => $validated['model'],
                'serial_number' => $validated['serial_number'] ?? null,
                'problem_desc'  => $validated['problem_desc'],
                'status'        => 'Pending',
            ]);

            // Simpan foto
            $photoPath = null;
            if ($request->hasFile('photo_entry')) {
                $photoPath = $request->file('photo_entry')
                    ->store("tickets/{$ticket->id}/entry", 'public');
            }

            // Simpan tanda tangan
            $sigPath = null;
            if (! empty($validated['sig_entry'])) {
                $sigPath = $this->saveBase64Signature(
                    $validated['sig_entry'],
                    "tickets/{$ticket->id}/entry",
                    'signature_entry'
                );
            }

            // Gabungkan aksesori
            $accessories = $validated['accessories'] ?? [];
            if (! empty($request->input('accessories_other'))) {
                $accessories[] = 'Lain-lain: ' . trim($request->input('accessories_other'));
            }

            if ($photoPath || $sigPath || $accessories || ! empty($validated['physical_condition']) || ! empty($validated['device_password'])) {
                ServiceAsset::updateOrCreate(
                    ['ticket_id' => $ticket->id],
                    [
                        'photo_entry'        => $photoPath,
                        'sig_entry'          => $sigPath,
                        'accessories'        => $accessories ?: null,
                        'physical_condition' => $validated['physical_condition'] ?? null,
                        'device_password'    => $validated['device_password']    ?? null,
                    ]
                );
            }

            ServiceLog::create([
                'ticket_id' => $ticket->id,
                'user_id'   => auth()->id(),
                'note'      => 'Data perangkat diisi kurir setelah pickup. Status: Pending.',
            ]);
        });

        return redirect()->route('courier.pickup')
            ->with('success', "Tiket {$ticket->ticket_code} berhasil dilengkapi dan masuk antrian teknisi.");
    }

    /**
     * Daftar tiket yang siap untuk delivery ke customer.
     */
    public function delivery(Request $request)
    {
        $search = trim((string) $request->query('search', ''));
        $queueType = (string) $request->query('queue_type', 'all');

        if (! in_array($queueType, ['all', 'service', 'sale'], true)) {
            $queueType = 'all';
        }

        $serviceQuery = ServiceTicket::whereIn('status', ['Ready', 'Cancelled'])
            ->with('customer')
            ->orderBy('updated_at')
            ->when($search !== '', function ($query) use ($search) {
                $query->where(function ($inner) use ($search) {
                    $inner->where('ticket_code', 'like', "%{$search}%")
                        ->orWhere('brand', 'like', "%{$search}%")
                        ->orWhere('model', 'like', "%{$search}%")
                        ->orWhereHas('customer', fn ($customer) =>
                            $customer->where('name', 'like', "%{$search}%")
                                ->orWhere('whatsapp', 'like', "%{$search}%")
                        );
                });
            });

        $saleQuery = Invoice::where('source_type', Invoice::SOURCE_SALE)
            ->where('status', Invoice::STATUS_ISSUED)
            ->whereNull('delivered_at')
            ->with(['customer', 'items'])
            ->when($search !== '', function ($query) use ($search) {
                $query->where(function ($inner) use ($search) {
                    $inner->where('invoice_number', 'like', "%{$search}%")
                        ->orWhereHas('customer', fn ($customer) =>
                            $customer->where('name', 'like', "%{$search}%")
                                ->orWhere('whatsapp', 'like', "%{$search}%")
                        )
                        ->orWhereHas('items', fn ($items) => $items->where('description', 'like', "%{$search}%"));
                });
            })
            ->orderByDesc('issued_at');

        $tickets = $queueType === 'sale'
            ? ServiceTicket::whereRaw('1 = 0')->paginate(20, ['*'], 'service_page')->withQueryString()
            : $serviceQuery->paginate(20, ['*'], 'service_page')->withQueryString();

        $saleInvoices = $queueType === 'service'
            ? Invoice::whereRaw('1 = 0')->paginate(20, ['*'], 'sale_page')->withQueryString()
            : $saleQuery->paginate(20, ['*'], 'sale_page')->withQueryString();

        $today = now()->startOfDay();
        $weekStart = now()->startOfWeek();

        $stats = [
            'service_queue' => ServiceTicket::whereIn('status', ['Ready', 'Cancelled'])->count(),
            'sale_queue' => Invoice::where('source_type', Invoice::SOURCE_SALE)
                ->where('status', Invoice::STATUS_ISSUED)
                ->whereNull('delivered_at')
                ->count(),
            'service_delivered_today' => ServiceTicket::whereNotNull('picked_up_at')->where('picked_up_at', '>=', $today)->count(),
            'sale_delivered_today' => Invoice::where('source_type', Invoice::SOURCE_SALE)->whereNotNull('delivered_at')->where('delivered_at', '>=', $today)->count(),
            'service_delivered_week' => ServiceTicket::whereNotNull('picked_up_at')->where('picked_up_at', '>=', $weekStart)->count(),
            'sale_delivered_week' => Invoice::where('source_type', Invoice::SOURCE_SALE)->whereNotNull('delivered_at')->where('delivered_at', '>=', $weekStart)->count(),
        ];

        $recentServiceDeliveries = ServiceTicket::whereNotNull('picked_up_at')
            ->with([
                'customer',
                'logs' => fn ($q) => $q->with('user')->latest('created_at'),
            ])
            ->latest('picked_up_at')
            ->limit(6)
            ->get();

        $recentSaleDeliveries = Invoice::where('source_type', Invoice::SOURCE_SALE)
            ->whereNotNull('delivered_at')
            ->with(['customer', 'deliverer'])
            ->latest('delivered_at')
            ->limit(6)
            ->get();

        return view('courier.delivery', compact(
            'tickets',
            'saleInvoices',
            'search',
            'queueType',
            'stats',
            'recentServiceDeliveries',
            'recentSaleDeliveries'
        ));
    }

    public function showSaleDelivery(Invoice $invoice)
    {
        $this->abortUnlessDeliverableSaleInvoice($invoice);
        $invoice->load(['customer', 'items']);

        return view('courier.sale-delivery', compact('invoice'));
    }

    public function storeSaleDelivery(Request $request, Invoice $invoice)
    {
        $this->abortUnlessDeliverableSaleInvoice($invoice);

        $data = $request->validate([
            'recipient_name' => ['required', 'string', 'max:255'],
            'delivery_note' => ['nullable', 'string', 'max:1000'],
            'delivery_photo' => ['nullable', 'image', 'max:5120'],
            'delivery_signature' => ['required', 'string'],
        ]);

        $photoPath = $request->hasFile('delivery_photo')
            ? $request->file('delivery_photo')->store("invoices/{$invoice->id}/delivery", 'public')
            : null;

        $signaturePath = $this->saveBase64Signature(
            $data['delivery_signature'],
            "invoices/{$invoice->id}/delivery",
            'signature_delivery'
        );

        $invoice->update([
            'delivered_at' => now(),
            'delivered_by' => auth()->id(),
            'delivery_recipient' => $data['recipient_name'],
            'delivery_note' => $data['delivery_note'] ?? null,
            'delivery_photo_path' => $photoPath,
            'delivery_signature_path' => $signaturePath,
            'updated_by' => auth()->id(),
        ]);

        InvoiceActivityLog::create([
            'invoice_id' => $invoice->id,
            'user_id' => auth()->id(),
            'action' => 'delivered',
            'description' => 'Delivery barang pembelian selesai. Diterima oleh "' . $data['recipient_name'] . '".',
            'meta' => [
                'delivery_note' => $data['delivery_note'] ?? null,
                'delivery_photo_path' => $photoPath,
                'delivery_signature_path' => $signaturePath,
            ],
        ]);

        return redirect()->route('courier.delivery')
            ->with('success', 'Delivery barang pembelian berhasil dikonfirmasi.');
    }

    private function abortUnlessDeliverableSaleInvoice(Invoice $invoice): void
    {
        abort_unless(
            $invoice->source_type === Invoice::SOURCE_SALE &&
            $invoice->status === Invoice::STATUS_ISSUED &&
            $invoice->delivered_at === null,
            404,
            'Invoice penjualan ini tidak tersedia untuk delivery.'
        );
    }

    private function saveBase64Signature(string $base64, string $directory, string $filename): string
    {
        $data = preg_replace('/^data:image\/\w+;base64,/', '', $base64);
        $data = base64_decode((string) $data, true);

        if ($data === false) {
            abort(422, 'Format tanda tangan delivery tidak valid.');
        }

        $path = $directory . '/' . $filename . '_' . now()->format('YmdHis') . '.png';
        Storage::disk('public')->put($path, $data);

        return $path;
    }
}
