<?php

namespace App\Services;

use App\Models\Orders\Order;
use App\Models\Tenants\Shipment;
use App\Models\Tenants\ShipmentItem;
use App\Models\Tenants\ShipmentVehicleDispatch;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;

class ShipmentService extends Service
{
    /**
     * 출하 목록 조회
     */
    public function index(array $params): LengthAwarePaginator
    {
        $tenantId = $this->tenantId();

        $query = Shipment::query()
            ->where('tenant_id', $tenantId)
            ->with(['items', 'vehicleDispatches', 'order.client', 'order.writer', 'workOrder']);

        // 검색어 필터
        if (! empty($params['search'])) {
            $search = $params['search'];
            $query->where(function ($q) use ($search) {
                $q->where('shipment_no', 'like', "%{$search}%")
                    ->orWhere('lot_no', 'like', "%{$search}%")
                    ->orWhere('customer_name', 'like', "%{$search}%")
                    ->orWhere('site_name', 'like', "%{$search}%");
            });
        }

        // 상태 필터
        if (! empty($params['status'])) {
            $query->where('status', $params['status']);
        }

        // 우선순위 필터
        if (! empty($params['priority'])) {
            $query->where('priority', $params['priority']);
        }

        // 배송방식 필터
        if (! empty($params['delivery_method'])) {
            $query->where('delivery_method', $params['delivery_method']);
        }

        // 예정일 범위 필터
        if (! empty($params['scheduled_from'])) {
            $query->where('scheduled_date', '>=', $params['scheduled_from']);
        }
        if (! empty($params['scheduled_to'])) {
            $query->where('scheduled_date', '<=', $params['scheduled_to']);
        }

        // 출하가능 필터
        if (isset($params['can_ship'])) {
            $query->where('can_ship', (bool) $params['can_ship']);
        }

        // 입금확인 필터
        if (isset($params['deposit_confirmed'])) {
            $query->where('deposit_confirmed', (bool) $params['deposit_confirmed']);
        }

        // 정렬
        $sortBy = $params['sort_by'] ?? 'scheduled_date';
        $sortDir = $params['sort_dir'] ?? 'desc';
        $query->orderBy($sortBy, $sortDir);

        // 페이지네이션
        $perPage = $params['per_page'] ?? 20;

        return $query->paginate($perPage);
    }

    /**
     * 출하 통계 조회
     */
    public function stats(): array
    {
        $tenantId = $this->tenantId();

        $total = Shipment::where('tenant_id', $tenantId)->count();

        $scheduled = Shipment::where('tenant_id', $tenantId)
            ->where('status', 'scheduled')
            ->count();

        $ready = Shipment::where('tenant_id', $tenantId)
            ->where('status', 'ready')
            ->count();

        $shipping = Shipment::where('tenant_id', $tenantId)
            ->where('status', 'shipping')
            ->count();

        $completed = Shipment::where('tenant_id', $tenantId)
            ->where('status', 'completed')
            ->count();

        $urgent = Shipment::where('tenant_id', $tenantId)
            ->where('priority', 'urgent')
            ->whereIn('status', ['scheduled', 'ready'])
            ->count();

        $todayScheduled = Shipment::where('tenant_id', $tenantId)
            ->whereDate('scheduled_date', now())
            ->count();

        return [
            'total' => $total,
            'scheduled' => $scheduled,
            'ready' => $ready,
            'shipping' => $shipping,
            'completed' => $completed,
            'urgent' => $urgent,
            'today_scheduled' => $todayScheduled,
            // 프론트엔드 호환 필드 (snake_case)
            'today_shipment_count' => $todayScheduled,
            'scheduled_count' => $scheduled,
            'shipping_count' => $shipping,
            'urgent_count' => $urgent,
        ];
    }

    /**
     * 상태별 통계 (탭용)
     */
    public function statsByStatus(): array
    {
        $tenantId = $this->tenantId();

        $stats = Shipment::where('tenant_id', $tenantId)
            ->selectRaw('status, COUNT(*) as count')
            ->groupBy('status')
            ->get()
            ->keyBy('status');

        $result = [];
        foreach (Shipment::STATUSES as $key => $label) {
            $data = $stats->get($key);
            $result[$key] = [
                'label' => $label,
                'count' => $data?->count ?? 0,
            ];
        }

        return $result;
    }

    /**
     * 출하 상세 조회
     */
    public function show(int $id): Shipment
    {
        $tenantId = $this->tenantId();

        return Shipment::query()
            ->where('tenant_id', $tenantId)
            ->with([
                'items' => function ($query) {
                    $query->orderBy('seq');
                },
                'vehicleDispatches',
                'order.client',
                'order.writer',
                'workOrder',
                'creator',
                'updater',
            ])
            ->findOrFail($id);
    }

    /**
     * 출하 생성
     */
    public function store(array $data): Shipment
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        return DB::transaction(function () use ($data, $tenantId, $userId) {
            // 출하번호 자동 생성
            $shipmentNo = $data['shipment_no'] ?? Shipment::generateShipmentNo($tenantId);

            $shipment = Shipment::create([
                'tenant_id' => $tenantId,
                'shipment_no' => $shipmentNo,
                'lot_no' => $data['lot_no'] ?? null,
                'order_id' => $data['order_id'] ?? null,
                'scheduled_date' => $data['scheduled_date'],
                'status' => $data['status'] ?? 'scheduled',
                'priority' => $data['priority'] ?? 'normal',
                'delivery_method' => $data['delivery_method'] ?? 'pickup',
                // 발주처/배송 정보
                'client_id' => $data['client_id'] ?? null,
                'customer_name' => $data['customer_name'] ?? null,
                'site_name' => $data['site_name'] ?? null,
                'delivery_address' => $data['delivery_address'] ?? null,
                'receiver' => $data['receiver'] ?? null,
                'receiver_contact' => $data['receiver_contact'] ?? null,
                // 상태 플래그
                'can_ship' => $data['can_ship'] ?? false,
                'deposit_confirmed' => $data['deposit_confirmed'] ?? false,
                'invoice_issued' => $data['invoice_issued'] ?? false,
                'customer_grade' => $data['customer_grade'] ?? null,
                // 상차 정보
                'loading_manager' => $data['loading_manager'] ?? null,
                'loading_time' => $data['loading_time'] ?? null,
                // 물류/배차 정보
                'logistics_company' => $data['logistics_company'] ?? null,
                'vehicle_tonnage' => $data['vehicle_tonnage'] ?? null,
                'shipping_cost' => $data['shipping_cost'] ?? null,
                // 차량/운전자 정보
                'vehicle_no' => $data['vehicle_no'] ?? null,
                'driver_name' => $data['driver_name'] ?? null,
                'driver_contact' => $data['driver_contact'] ?? null,
                'expected_arrival' => $data['expected_arrival'] ?? null,
                // 기타
                'remarks' => $data['remarks'] ?? null,
                'created_by' => $userId,
            ]);

            // 출하 품목 추가
            if (! empty($data['items'])) {
                $this->syncItems($shipment, $data['items'], $tenantId);
            }

            // 배차정보 추가
            if (! empty($data['vehicle_dispatches'])) {
                $this->syncDispatches($shipment, $data['vehicle_dispatches'], $tenantId);
            }

            return $shipment->load(['items', 'vehicleDispatches']);
        });
    }

    /**
     * 출하 수정
     */
    public function update(int $id, array $data): Shipment
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        return DB::transaction(function () use ($id, $data, $tenantId, $userId) {
            $shipment = Shipment::where('tenant_id', $tenantId)->findOrFail($id);

            $shipment->update([
                'lot_no' => $data['lot_no'] ?? $shipment->lot_no,
                'order_id' => $data['order_id'] ?? $shipment->order_id,
                'scheduled_date' => $data['scheduled_date'] ?? $shipment->scheduled_date,
                'priority' => $data['priority'] ?? $shipment->priority,
                'delivery_method' => $data['delivery_method'] ?? $shipment->delivery_method,
                // 발주처/배송 정보
                'client_id' => $data['client_id'] ?? $shipment->client_id,
                'customer_name' => $data['customer_name'] ?? $shipment->customer_name,
                'site_name' => $data['site_name'] ?? $shipment->site_name,
                'delivery_address' => $data['delivery_address'] ?? $shipment->delivery_address,
                'receiver' => $data['receiver'] ?? $shipment->receiver,
                'receiver_contact' => $data['receiver_contact'] ?? $shipment->receiver_contact,
                // 상태 플래그
                'can_ship' => $data['can_ship'] ?? $shipment->can_ship,
                'deposit_confirmed' => $data['deposit_confirmed'] ?? $shipment->deposit_confirmed,
                'invoice_issued' => $data['invoice_issued'] ?? $shipment->invoice_issued,
                'customer_grade' => $data['customer_grade'] ?? $shipment->customer_grade,
                // 상차 정보
                'loading_manager' => $data['loading_manager'] ?? $shipment->loading_manager,
                'loading_time' => $data['loading_time'] ?? $shipment->loading_time,
                // 물류/배차 정보
                'logistics_company' => $data['logistics_company'] ?? $shipment->logistics_company,
                'vehicle_tonnage' => $data['vehicle_tonnage'] ?? $shipment->vehicle_tonnage,
                'shipping_cost' => $data['shipping_cost'] ?? $shipment->shipping_cost,
                // 차량/운전자 정보
                'vehicle_no' => $data['vehicle_no'] ?? $shipment->vehicle_no,
                'driver_name' => $data['driver_name'] ?? $shipment->driver_name,
                'driver_contact' => $data['driver_contact'] ?? $shipment->driver_contact,
                'expected_arrival' => $data['expected_arrival'] ?? $shipment->expected_arrival,
                // 기타
                'remarks' => $data['remarks'] ?? $shipment->remarks,
                'updated_by' => $userId,
            ]);

            // 출하 품목 동기화
            if (isset($data['items'])) {
                $this->syncItems($shipment, $data['items'], $tenantId);
            }

            // 배차정보 동기화
            if (isset($data['vehicle_dispatches'])) {
                $this->syncDispatches($shipment, $data['vehicle_dispatches'], $tenantId);
            }

            return $shipment->load(['items', 'vehicleDispatches']);
        });
    }

    /**
     * 출하 상태 변경
     */
    public function updateStatus(int $id, string $status, ?array $additionalData = null): Shipment
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        $shipment = Shipment::where('tenant_id', $tenantId)->findOrFail($id);

        $updateData = [
            'status' => $status,
            'updated_by' => $userId,
        ];

        // 상태별 추가 데이터
        if ($status === 'ready' && isset($additionalData['loading_time'])) {
            $updateData['loading_time'] = $additionalData['loading_time'];
        }

        if ($status === 'shipping') {
            if (isset($additionalData['loading_completed_at'])) {
                $updateData['loading_completed_at'] = $additionalData['loading_completed_at'];
            } else {
                $updateData['loading_completed_at'] = now();
            }

            if (isset($additionalData['vehicle_no'])) {
                $updateData['vehicle_no'] = $additionalData['vehicle_no'];
            }
            if (isset($additionalData['driver_name'])) {
                $updateData['driver_name'] = $additionalData['driver_name'];
            }
            if (isset($additionalData['driver_contact'])) {
                $updateData['driver_contact'] = $additionalData['driver_contact'];
            }
        }

        if ($status === 'completed' && isset($additionalData['confirmed_arrival'])) {
            $updateData['confirmed_arrival'] = $additionalData['confirmed_arrival'];
        }

        $previousStatus = $shipment->status;
        $shipment->update($updateData);

        // 🆕 출하완료 시 재고 차감 (FIFO)
        if ($status === 'completed' && $previousStatus !== 'completed') {
            $this->decreaseStockForShipment($shipment);
        }

        // 연결된 수주(Order) 상태 동기화
        $this->syncOrderStatus($shipment, $tenantId);

        return $shipment->load(['items', 'vehicleDispatches']);
    }

    /**
     * 출하 완료 시 재고 차감
     */
    private function decreaseStockForShipment(Shipment $shipment): void
    {
        $stockService = app(StockService::class);

        // 출하 품목 조회
        $items = $shipment->items;

        foreach ($items as $item) {
            // item_id가 없는 경우 item_code로 품목 조회 시도
            $itemId = $item->item_id;

            if (! $itemId && $item->item_code) {
                $tenantId = $this->tenantId();
                $foundItem = \App\Models\Items\Item::where('tenant_id', $tenantId)
                    ->where('code', $item->item_code)
                    ->first();
                $itemId = $foundItem?->id;
            }

            if (! $itemId || ! $item->quantity) {
                continue;
            }

            try {
                $stockService->decreaseForShipment(
                    itemId: $itemId,
                    qty: (float) $item->quantity,
                    shipmentId: $shipment->id,
                    stockLotId: $item->stock_lot_id
                );
            } catch (\Exception $e) {
                // 재고 부족 등의 에러는 로그만 기록하고 계속 진행
                \Illuminate\Support\Facades\Log::warning('Failed to decrease stock for shipment item', [
                    'shipment_id' => $shipment->id,
                    'item_code' => $item->item_code,
                    'quantity' => $item->quantity,
                    'error' => $e->getMessage(),
                ]);
            }
        }
    }

    /**
     * 출하 상태 변경 시 연결된 수주(Order) 상태 동기화
     *
     * 매핑 규칙:
     * - 'shipping' → Order::STATUS_SHIPPING (출하중)
     * - 'completed' → Order::STATUS_SHIPPED (출하완료)
     */
    private function syncOrderStatus(Shipment $shipment, int $tenantId): void
    {
        // 수주 연결이 없으면 스킵
        if (! $shipment->order_id) {
            return;
        }

        $order = Order::where('tenant_id', $tenantId)->find($shipment->order_id);
        if (! $order) {
            return;
        }

        // 출하 상태 → 수주 상태 매핑
        $statusMap = [
            'shipping' => Order::STATUS_SHIPPING,
            'completed' => Order::STATUS_SHIPPED,
        ];

        $newOrderStatus = $statusMap[$shipment->status] ?? null;

        // 매핑되는 상태가 없거나 이미 동일한 상태면 스킵
        if (! $newOrderStatus || $order->status_code === $newOrderStatus) {
            return;
        }

        $order->status_code = $newOrderStatus;
        $order->updated_by = $this->apiUserId();
        $order->save();
    }

    /**
     * 출하 삭제
     */
    public function delete(int $id): bool
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        $shipment = Shipment::where('tenant_id', $tenantId)->findOrFail($id);

        return DB::transaction(function () use ($shipment, $userId) {
            // 품목 삭제
            $shipment->items()->delete();

            // 배차정보 삭제
            $shipment->vehicleDispatches()->delete();

            // 출하 삭제
            $shipment->update(['deleted_by' => $userId]);
            $shipment->delete();

            return true;
        });
    }

    /**
     * 출하 품목 동기화
     */
    protected function syncItems(Shipment $shipment, array $items, int $tenantId): void
    {
        // 기존 품목 삭제
        $shipment->items()->forceDelete();

        // 새 품목 생성
        $seq = 1;
        foreach ($items as $item) {
            ShipmentItem::create([
                'tenant_id' => $tenantId,
                'shipment_id' => $shipment->id,
                'seq' => $item['seq'] ?? $seq,
                'item_id' => $item['item_id'] ?? null,
                'item_code' => $item['item_code'] ?? null,
                'item_name' => $item['item_name'],
                'floor_unit' => $item['floor_unit'] ?? null,
                'specification' => $item['specification'] ?? null,
                'quantity' => $item['quantity'] ?? 0,
                'unit' => $item['unit'] ?? null,
                'lot_no' => $item['lot_no'] ?? null,
                'stock_lot_id' => $item['stock_lot_id'] ?? null,
                'remarks' => $item['remarks'] ?? null,
            ]);
            $seq++;
        }
    }

    /**
     * 배차정보 동기화
     */
    protected function syncDispatches(Shipment $shipment, array $dispatches, int $tenantId): void
    {
        // 기존 배차정보 삭제
        $shipment->vehicleDispatches()->forceDelete();

        // 새 배차정보 생성
        $seq = 1;
        foreach ($dispatches as $dispatch) {
            ShipmentVehicleDispatch::create([
                'tenant_id' => $tenantId,
                'shipment_id' => $shipment->id,
                'seq' => $dispatch['seq'] ?? $seq,
                'logistics_company' => $dispatch['logistics_company'] ?? null,
                'arrival_datetime' => $dispatch['arrival_datetime'] ?? null,
                'tonnage' => $dispatch['tonnage'] ?? null,
                'vehicle_no' => $dispatch['vehicle_no'] ?? null,
                'driver_contact' => $dispatch['driver_contact'] ?? null,
                'remarks' => $dispatch['remarks'] ?? null,
                'options' => $dispatch['options'] ?? null,
            ]);
            $seq++;
        }
    }

    /**
     * LOT 옵션 조회 (출고 가능한 LOT 목록)
     */
    public function getLotOptions(): array
    {
        $tenantId = $this->tenantId();

        return \App\Models\Tenants\StockLot::query()
            ->where('tenant_id', $tenantId)
            ->whereIn('status', ['available', 'reserved'])
            ->where('qty', '>', 0)
            ->with('stock:id,item_code,item_name')
            ->orderBy('fifo_order')
            ->get()
            ->map(function ($lot) {
                return [
                    'id' => $lot->id,
                    'lot_no' => $lot->lot_no,
                    'item_code' => $lot->stock?->item_code,
                    'item_name' => $lot->stock?->item_name,
                    'qty' => $lot->qty,
                    'available_qty' => $lot->available_qty,
                    'unit' => $lot->unit,
                    'location' => $lot->location,
                    'fifo_order' => $lot->fifo_order,
                ];
            })
            ->toArray();
    }

    /**
     * 물류사 옵션 조회
     */
    public function getLogisticsOptions(): array
    {
        // TODO: 별도 물류사 테이블이 있다면 조회
        // 현재는 기본값 반환
        return [
            ['value' => '한진택배', 'label' => '한진택배'],
            ['value' => '롯데택배', 'label' => '롯데택배'],
            ['value' => 'CJ대한통운', 'label' => 'CJ대한통운'],
            ['value' => '우체국택배', 'label' => '우체국택배'],
            ['value' => '로젠택배', 'label' => '로젠택배'],
            ['value' => '경동택배', 'label' => '경동택배'],
            ['value' => '직접입력', 'label' => '직접입력'],
        ];
    }

    /**
     * 차량 톤수 옵션 조회
     */
    public function getVehicleTonnageOptions(): array
    {
        return [
            ['value' => '1톤', 'label' => '1톤'],
            ['value' => '2.5톤', 'label' => '2.5톤'],
            ['value' => '5톤', 'label' => '5톤'],
            ['value' => '11톤', 'label' => '11톤'],
            ['value' => '25톤', 'label' => '25톤'],
        ];
    }
}
