<?php

namespace App\Services;

use App\Models\Orders\Order;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;

class ProductionOrderService extends Service
{
    /**
     * 생산지시 대상 상태 코드
     */
    private const PRODUCTION_STATUSES = [
        Order::STATUS_IN_PROGRESS,
        Order::STATUS_IN_PRODUCTION,
        Order::STATUS_PRODUCED,
        Order::STATUS_SHIPPING,
        Order::STATUS_SHIPPED,
    ];

    /**
     * 생산지시 목록 조회
     */
    public function index(array $params): LengthAwarePaginator
    {
        $tenantId = $this->tenantId();

        $query = Order::query()
            ->where('tenant_id', $tenantId)
            ->whereIn('status_code', self::PRODUCTION_STATUSES)
            ->with(['client', 'workOrders.process', 'workOrders.assignees.user'])
            ->withCount([
                'workOrders' => fn ($q) => $q->whereNotNull('process_id')
                    ->where(fn ($q2) => $q2->whereNull('options->is_auxiliary')
                        ->orWhere('options->is_auxiliary', false)),
                'nodes',
            ]);

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

        // 생산 상태 필터
        if (! empty($params['production_status'])) {
            switch ($params['production_status']) {
                case 'waiting':
                    $query->where('status_code', Order::STATUS_IN_PROGRESS);
                    break;
                case 'in_production':
                    $query->where('status_code', Order::STATUS_IN_PRODUCTION);
                    break;
                case 'completed':
                    $query->whereIn('status_code', [
                        Order::STATUS_PRODUCED,
                        Order::STATUS_SHIPPING,
                        Order::STATUS_SHIPPED,
                    ]);
                    break;
            }
        }

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

        // 페이지네이션
        $perPage = $params['per_page'] ?? 20;
        $result = $query->paginate($perPage);

        // 가공 필드 추가
        $result->getCollection()->transform(function (Order $order) {
            $minCreatedAt = $order->workOrders->min('created_at');
            $order->production_ordered_at = $minCreatedAt
                ? $minCreatedAt->format('Y-m-d')
                : null;

            // 개소수 (order_nodes 수)
            $order->node_count = $order->nodes_count ?? 0;

            // 주요 생산 공정 WO만 (구매품 + 보조 공정 제외)
            $productionWOs = $this->filterMainProductionWOs($order->workOrders);
            $order->work_order_progress = [
                'total' => $productionWOs->count(),
                'completed' => $productionWOs->where('status', 'completed')->count()
                    + $productionWOs->where('status', 'shipped')->count(),
                'in_progress' => $productionWOs->where('status', 'in_progress')->count(),
            ];

            // 프론트 탭용 production_status 매핑
            $order->production_status = $this->mapProductionStatus($order->status_code);

            return $order;
        });

        return $result;
    }

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

        $waiting = Order::where('tenant_id', $tenantId)
            ->where('status_code', Order::STATUS_IN_PROGRESS)
            ->count();

        $inProduction = Order::where('tenant_id', $tenantId)
            ->where('status_code', Order::STATUS_IN_PRODUCTION)
            ->count();

        $completed = Order::where('tenant_id', $tenantId)
            ->whereIn('status_code', [
                Order::STATUS_PRODUCED,
                Order::STATUS_SHIPPING,
                Order::STATUS_SHIPPED,
            ])
            ->count();

        return [
            'total' => $waiting + $inProduction + $completed,
            'waiting' => $waiting,
            'in_production' => $inProduction,
            'completed' => $completed,
        ];
    }

    /**
     * 생산지시 상세 조회
     */
    public function show(int $orderId): array
    {
        $tenantId = $this->tenantId();

        $order = Order::query()
            ->where('tenant_id', $tenantId)
            ->whereIn('status_code', self::PRODUCTION_STATUSES)
            ->with([
                'client',
                'workOrders.process',
                'workOrders.items',
                'workOrders.assignees.user',
                'nodes',
            ])
            ->withCount('nodes')
            ->findOrFail($orderId);

        // 생산지시일 (날짜만)
        $minCreatedAt = $order->workOrders->min('created_at');
        $order->production_ordered_at = $minCreatedAt
            ? $minCreatedAt->format('Y-m-d')
            : null;
        $order->production_status = $this->mapProductionStatus($order->status_code);

        // 주요 생산 공정 WO만 필터 (구매품 + 보조 공정 제외)
        $productionWorkOrders = $this->filterMainProductionWOs($order->workOrders);

        // WorkOrder 진행 현황 (생산 공정 기준)
        $workOrderProgress = [
            'total' => $productionWorkOrders->count(),
            'completed' => $productionWorkOrders->where('status', 'completed')->count()
                + $productionWorkOrders->where('status', 'shipped')->count(),
            'in_progress' => $productionWorkOrders->where('status', 'in_progress')->count(),
        ];

        // WorkOrder 목록 가공 (생산 공정만)
        $workOrders = $productionWorkOrders->values()->map(function ($wo) {
            return [
                'id' => $wo->id,
                'work_order_no' => $wo->work_order_no,
                'process_name' => $wo->process?->process_name ?? '',
                'quantity' => $wo->items->count(),
                'status' => $wo->status,
                'assignees' => $wo->assignees->map(fn ($a) => $a->user?->name ?? '')->filter()->values()->toArray(),
            ];
        });

        // BOM 데이터 (order_nodes에서 추출)
        $bomProcessGroups = $this->extractBomProcessGroups($order->nodes);

        return [
            'order' => $order->makeHidden(['workOrders', 'nodes']),
            'production_ordered_at' => $order->production_ordered_at,
            'production_status' => $order->production_status,
            'node_count' => $order->nodes_count ?? 0,
            'work_order_progress' => $workOrderProgress,
            'work_orders' => $workOrders,
            'bom_process_groups' => $bomProcessGroups,
        ];
    }

    /**
     * Order status_code → 프론트 production_status 매핑
     */
    private function mapProductionStatus(string $statusCode): string
    {
        return match ($statusCode) {
            Order::STATUS_IN_PROGRESS => 'waiting',
            Order::STATUS_IN_PRODUCTION => 'in_production',
            default => 'completed',
        };
    }

    /**
     * order_nodes에서 BOM 공정 분류 추출
     *
     * bom_result 구조: { items: [...], success, subtotals, ... }
     * 각 item: { item_id, item_code, item_name, process_group, specification, quantity, unit, ... }
     */
    private function extractBomProcessGroups($nodes): array
    {
        $groups = [];

        foreach ($nodes as $node) {
            $bomResult = $node->options['bom_result'] ?? null;
            if (! $bomResult || ! is_array($bomResult)) {
                continue;
            }

            // bom_result.items 배열에서 추출
            $items = $bomResult['items'] ?? [];
            if (! is_array($items)) {
                continue;
            }

            $nodeName = $node->name ?? '';

            foreach ($items as $item) {
                if (! is_array($item)) {
                    continue;
                }

                $processGroup = $item['process_group'] ?? $item['category_group'] ?? '기타';

                if (! isset($groups[$processGroup])) {
                    $groups[$processGroup] = [
                        'process_name' => $processGroup,
                        'items' => [],
                    ];
                }

                $groups[$processGroup]['items'][] = [
                    'id' => $item['item_id'] ?? null,
                    'item_code' => $item['item_code'] ?? '',
                    'item_name' => $item['item_name'] ?? '',
                    'spec' => $item['specification'] ?? '',
                    'unit' => $item['unit'] ?? '',
                    'quantity' => $item['quantity'] ?? 0,
                    'unit_price' => $item['unit_price'] ?? 0,
                    'total_price' => $item['total_price'] ?? 0,
                    'node_name' => $nodeName,
                ];
            }
        }

        return array_values($groups);
    }

    /**
     * 주요 생산 공정 WO만 필터 (구매품/서비스 + 보조 공정 제외)
     *
     * 제외 대상:
     * - process_id가 null인 WO (구매품/서비스)
     * - options.is_auxiliary가 true인 WO (재고생산 등 보조 공정)
     */
    private function filterMainProductionWOs($workOrders): \Illuminate\Support\Collection
    {
        return $workOrders->filter(function ($wo) {
            if (empty($wo->process_id)) {
                return false;
            }
            $options = is_array($wo->options) ? $wo->options : (json_decode($wo->options, true) ?? []);

            return empty($options['is_auxiliary']);
        });
    }
}
