<?php

namespace App\Services\Transaction;

use App\Models\Transaction\Order;
use App\Models\Transaction\OrderItem;
use App\Models\Transaction\Invoice;
use App\Models\Transaction\DispenseRecord;
use Illuminate\Support\Facades\DB;
use App\Models\Machine\Machine;

class TransactionService
{
    /**
     * Process a new transaction (B600).
     */
    public function processTransaction(array $data): Order
    {
        return DB::transaction(function () use ($data) {
            $machine = Machine::where('serial_no', $data['serial_no'])->firstOrFail();
            
            // Create Order
            $order = Order::create([
                'company_id' => $machine->company_id,
                'flow_id' => $data['flow_id'] ?? null,
                'order_no' => $data['order_no'] ?? $this->generateOrderNo(),
                'machine_id' => $machine->id,
                'member_id' => $data['member_id'] ?? null,
                'total_amount' => $data['total_amount'],
                'discount_amount' => $data['discount_amount'] ?? 0,
                'pay_amount' => $data['pay_amount'],
                'payment_type' => $data['payment_type'] ?? 0,
                'payment_status' => $data['payment_status'] ?? 1,
                'payment_at' => now(),
                'status' => 'completed',
                'metadata' => $data['metadata'] ?? null,
            ]);

            // Create Order Items
            if (!empty($data['items'])) {
                foreach ($data['items'] as $item) {
                    $order->items()->create([
                        'product_id' => $item['product_id'],
                        'product_name' => $item['product_name'] ?? 'Unknown',
                        'barcode' => $item['barcode'] ?? null,
                        'price' => $item['price'],
                        'quantity' => $item['quantity'],
                        'subtotal' => $item['price'] * $item['quantity'],
                    ]);
                }
            }

            return $order;
        });
    }

    /**
     * Generate a unique order number.
     */
    protected function generateOrderNo(): string
    {
        return 'ORD-' . now()->format('YmdHis') . '-' . strtoupper(bin2hex(random_bytes(3)));
    }

    /**
     * Record Invoice (B601).
     */
    public function recordInvoice(array $data): Invoice
    {
        return DB::transaction(function () use ($data) {
            $machine = Machine::where('serial_no', $data['serial_no'])->firstOrFail();
            
            $order = null;
            if (!empty($data['flow_id'])) {
                $order = Order::where('flow_id', $data['flow_id'])->first();
            }

            return Invoice::create([
                'company_id' => $machine->company_id,
                'order_id' => $order?->id ?? ($data['order_id'] ?? null),
                'machine_id' => $machine->id,
                'flow_id' => $data['flow_id'] ?? null,
                'invoice_no' => $data['invoice_no'] ?? null,
                'amount' => $data['amount'] ?? 0,
                'carrier_id' => $data['carrier_id'] ?? null,
                'invoice_date' => $data['invoice_date'] ?? null,
                'random_number' => $data['random_no'] ?? null,
                'love_code' => $data['love_code'] ?? null,
                'metadata' => $data['metadata'] ?? null,
            ]);
        });
    }

    /**
     * Record dispense result (B602).
     */
    public function recordDispense(array $data): DispenseRecord
    {
        return DB::transaction(function () use ($data) {
            $machine = Machine::where('serial_no', $data['serial_no'])->firstOrFail();
            
            $order = null;
            if (!empty($data['flow_id'])) {
                $order = Order::where('flow_id', $data['flow_id'])->first();
            }

            return DispenseRecord::create([
                'company_id' => $machine->company_id,
                'order_id' => $order?->id ?? ($data['order_id'] ?? null),
                'flow_id' => $data['flow_id'] ?? null,
                'machine_id' => $machine->id,
                'slot_no' => $data['slot_no'] ?? 'unknown',
                'product_id' => $data['product_id'] ?? null,
                'amount' => $data['amount'] ?? 0,
                'dispense_status' => $data['dispense_status'] ?? 0,
                'machine_time' => $data['machine_time'] ?? now(),
            ]);
        });
    }
}
