<?php

namespace App\Modules\Procurement\Services;

use App\Modules\Procurement\Models\PurchaseOrder;
use App\Modules\Procurement\Models\PurchaseOrderItem;
use App\Modules\Procurement\Models\Vendor;
use App\Modules\Inventory\Contracts\InventoryServiceInterface;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Carbon;

class ProcurementAnalysisService
{
    public function __construct(
        protected InventoryServiceInterface $inventoryService,
    ) {}

    /**
     * 取得 KPI 總覽數據
     */
    public function getKPIs(array $filters): array
    {
        $dateFrom = $filters['date_from'] ?? Carbon::now()->subMonths(6)->format('Y-m-d');
        $dateTo = $filters['date_to'] ?? Carbon::now()->format('Y-m-d');
        $vendorId = $filters['vendor_id'] ?? null;
        $warehouseId = $filters['warehouse_id'] ?? null;

        // 採購單基礎查詢（排除草稿與已取消）
        $poQuery = PurchaseOrder::whereNotIn('status', ['draft', 'cancelled'])
            ->whereBetween('order_date', [$dateFrom, $dateTo]);
        if ($vendorId) $poQuery->where('vendor_id', $vendorId);
        if ($warehouseId) $poQuery->where('warehouse_id', $warehouseId);

        $totalAmount = (clone $poQuery)->sum('grand_total') ?: (clone $poQuery)->sum('total_amount');
        $totalOrders = (clone $poQuery)->count();

        // 進貨單查詢
        $grQuery = DB::table('goods_receipts')
            ->where('status', 'completed')
            ->whereBetween('received_date', [$dateFrom, $dateTo])
            ->whereNull('deleted_at');
        if ($vendorId) $grQuery->where('vendor_id', $vendorId);
        if ($warehouseId) $grQuery->where('warehouse_id', $warehouseId);

        $totalReceipts = (clone $grQuery)->count();

        // 平均交期天數（採購單→進貨單）
        $deliveryStats = DB::table('purchase_orders as po')
            ->join('goods_receipts as gr', 'gr.purchase_order_id', '=', 'po.id')
            ->whereNotIn('po.status', ['draft', 'cancelled'])
            ->where('gr.status', 'completed')
            ->whereNull('gr.deleted_at')
            ->whereBetween('po.order_date', [$dateFrom, $dateTo]);
        if ($vendorId) $deliveryStats->where('po.vendor_id', $vendorId);
        if ($warehouseId) $deliveryStats->where('po.warehouse_id', $warehouseId);

        $deliveryStats = $deliveryStats->selectRaw('
            AVG(DATEDIFF(gr.received_date, po.order_date)) as avg_days,
            COUNT(*) as total_linked,
            SUM(CASE WHEN gr.received_date <= po.expected_delivery_date THEN 1 ELSE 0 END) as on_time_count
        ')->first();

        $avgDays = round($deliveryStats->avg_days ?? 0, 1);
        $onTimeRate = $deliveryStats->total_linked > 0
            ? round(($deliveryStats->on_time_count / $deliveryStats->total_linked) * 100, 1)
            : 0;

        return [
            'total_amount' => (float) $totalAmount,
            'total_orders' => $totalOrders,
            'total_receipts' => $totalReceipts,
            'avg_delivery_days' => $avgDays,
            'on_time_rate' => $onTimeRate,
        ];
    }

    /**
     * 廠商供貨時效分析
     */
    public function getDeliveryAnalysis(array $filters): array
    {
        $dateFrom = $filters['date_from'] ?? Carbon::now()->subMonths(6)->format('Y-m-d');
        $dateTo = $filters['date_to'] ?? Carbon::now()->format('Y-m-d');
        $vendorId = $filters['vendor_id'] ?? null;
        $warehouseId = $filters['warehouse_id'] ?? null;

        $query = DB::table('purchase_orders as po')
            ->join('goods_receipts as gr', 'gr.purchase_order_id', '=', 'po.id')
            ->whereNotIn('po.status', ['draft', 'cancelled'])
            ->where('gr.status', 'completed')
            ->whereNull('gr.deleted_at')
            ->whereBetween('po.order_date', [$dateFrom, $dateTo]);
        if ($vendorId) $query->where('po.vendor_id', $vendorId);
        if ($warehouseId) $query->where('po.warehouse_id', $warehouseId);

        // 按廠商分組的交期統計
        $vendorDelivery = (clone $query)
            ->join('vendors', 'vendors.id', '=', 'po.vendor_id')
            ->groupBy('po.vendor_id', 'vendors.name')
            ->selectRaw('
                po.vendor_id,
                vendors.name as vendor_name,
                COUNT(*) as total_count,
                ROUND(AVG(DATEDIFF(gr.received_date, po.order_date)), 1) as avg_days,
                MIN(DATEDIFF(gr.received_date, po.order_date)) as min_days,
                MAX(DATEDIFF(gr.received_date, po.order_date)) as max_days,
                SUM(CASE WHEN gr.received_date <= po.expected_delivery_date THEN 1 ELSE 0 END) as on_time_count
            ')
            ->orderBy('avg_days', 'asc')
            ->get()
            ->map(function ($row) {
                $row->on_time_rate = $row->total_count > 0
                    ? round(($row->on_time_count / $row->total_count) * 100, 1) : 0;
                return $row;
            });

        // 延遲分佈統計
        $delayDistribution = (clone $query)
            ->selectRaw("
                CASE
                    WHEN DATEDIFF(gr.received_date, po.order_date) <= 0 THEN '提前到貨'
                    WHEN DATEDIFF(gr.received_date, po.order_date) BETWEEN 1 AND 3 THEN '1-3天'
                    WHEN DATEDIFF(gr.received_date, po.order_date) BETWEEN 4 AND 7 THEN '4-7天'
                    WHEN DATEDIFF(gr.received_date, po.order_date) BETWEEN 8 AND 14 THEN '8-14天'
                    ELSE '超過14天'
                END as category,
                COUNT(*) as count
            ")
            ->groupByRaw("
                CASE
                    WHEN DATEDIFF(gr.received_date, po.order_date) <= 0 THEN '提前到貨'
                    WHEN DATEDIFF(gr.received_date, po.order_date) BETWEEN 1 AND 3 THEN '1-3天'
                    WHEN DATEDIFF(gr.received_date, po.order_date) BETWEEN 4 AND 7 THEN '4-7天'
                    WHEN DATEDIFF(gr.received_date, po.order_date) BETWEEN 8 AND 14 THEN '8-14天'
                    ELSE '超過14天'
                END
            ")
            ->get();

        return [
            'vendor_delivery' => $vendorDelivery,
            'delay_distribution' => $delayDistribution,
        ];
    }

    /**
     * 進貨數量分析
     */
    public function getQuantityAnalysis(array $filters): array
    {
        $dateFrom = $filters['date_from'] ?? Carbon::now()->subMonths(6)->format('Y-m-d');
        $dateTo = $filters['date_to'] ?? Carbon::now()->format('Y-m-d');
        $vendorId = $filters['vendor_id'] ?? null;
        $warehouseId = $filters['warehouse_id'] ?? null;

        $baseQuery = DB::table('goods_receipts as gr')
            ->join('goods_receipt_items as gri', 'gri.goods_receipt_id', '=', 'gr.id')
            ->where('gr.status', 'completed')
            ->whereNull('gr.deleted_at')
            ->whereBetween('gr.received_date', [$dateFrom, $dateTo]);
        if ($vendorId) $baseQuery->where('gr.vendor_id', $vendorId);
        if ($warehouseId) $baseQuery->where('gr.warehouse_id', $warehouseId);

        // 月度進貨量趨勢
        $monthlyTrend = (clone $baseQuery)
            ->selectRaw("
                DATE_FORMAT(gr.received_date, '%Y-%m') as month,
                ROUND(SUM(gri.quantity_received), 2) as total_quantity,
                ROUND(SUM(gri.total_amount), 2) as total_amount,
                COUNT(DISTINCT gr.id) as receipt_count
            ")
            ->groupByRaw("DATE_FORMAT(gr.received_date, '%Y-%m')")
            ->orderBy('month', 'asc')
            ->get();

        // 廠商佔比（按進貨金額）
        $vendorShare = (clone $baseQuery)
            ->join('vendors', 'vendors.id', '=', 'gr.vendor_id')
            ->selectRaw('
                gr.vendor_id,
                vendors.name as vendor_name,
                ROUND(SUM(gri.total_amount), 2) as total_amount,
                ROUND(SUM(gri.quantity_received), 2) as total_quantity
            ')
            ->groupBy('gr.vendor_id', 'vendors.name')
            ->orderByDesc('total_amount')
            ->limit(10)
            ->get();

        // 商品進貨排行 Top 10
        $productRanking = (clone $baseQuery)
            ->join('products', 'products.id', '=', 'gri.product_id')
            ->selectRaw('
                gri.product_id,
                products.name as product_name,
                products.code as product_code,
                ROUND(SUM(gri.quantity_received), 2) as total_quantity,
                ROUND(SUM(gri.total_amount), 2) as total_amount
            ')
            ->groupBy('gri.product_id', 'products.name', 'products.code')
            ->orderByDesc('total_amount')
            ->limit(10)
            ->get();

        return [
            'monthly_trend' => $monthlyTrend,
            'vendor_share' => $vendorShare,
            'product_ranking' => $productRanking,
        ];
    }

    /**
     * 單價趨勢分析
     */
    public function getPriceTrendAnalysis(array $filters): array
    {
        $dateFrom = $filters['date_from'] ?? Carbon::now()->subMonths(6)->format('Y-m-d');
        $dateTo = $filters['date_to'] ?? Carbon::now()->format('Y-m-d');
        $vendorId = $filters['vendor_id'] ?? null;
        $warehouseId = $filters['warehouse_id'] ?? null;

        $baseQuery = DB::table('goods_receipts as gr')
            ->join('goods_receipt_items as gri', 'gri.goods_receipt_id', '=', 'gr.id')
            ->join('products', 'products.id', '=', 'gri.product_id')
            ->where('gr.status', 'completed')
            ->whereNull('gr.deleted_at')
            ->whereBetween('gr.received_date', [$dateFrom, $dateTo]);
        if ($vendorId) $baseQuery->where('gr.vendor_id', $vendorId);
        if ($warehouseId) $baseQuery->where('gr.warehouse_id', $warehouseId);

        // 商品月平均單價趨勢（取進貨金額 Top 10 的商品）
        $topProductIds = (clone $baseQuery)
            ->selectRaw('gri.product_id, SUM(gri.total_amount) as total')
            ->groupBy('gri.product_id')
            ->orderByDesc('total')
            ->limit(10)
            ->pluck('product_id');

        $priceTrend = [];
        if ($topProductIds->isNotEmpty()) {
            $priceTrend = (clone $baseQuery)
                ->whereIn('gri.product_id', $topProductIds->toArray())
                ->selectRaw("
                    gri.product_id,
                    products.name as product_name,
                    DATE_FORMAT(gr.received_date, '%Y-%m') as month,
                    ROUND(AVG(gri.unit_price), 2) as avg_price,
                    ROUND(MIN(gri.unit_price), 2) as min_price,
                    ROUND(MAX(gri.unit_price), 2) as max_price
                ")
                ->groupBy('gri.product_id', 'products.name', DB::raw("DATE_FORMAT(gr.received_date, '%Y-%m')"))
                ->orderBy('month', 'asc')
                ->get();
        }

        // 跨廠商比價（同一商品不同廠商的最近價格）
        $vendorComparison = (clone $baseQuery)
            ->join('vendors', 'vendors.id', '=', 'gr.vendor_id')
            ->whereIn('gri.product_id', $topProductIds->toArray())
            ->selectRaw('
                gri.product_id,
                products.name as product_name,
                gr.vendor_id,
                vendors.name as vendor_name,
                ROUND(AVG(gri.unit_price), 2) as avg_price,
                ROUND(MIN(gri.unit_price), 2) as min_price,
                ROUND(MAX(gri.unit_price), 2) as max_price,
                COUNT(*) as purchase_count
            ')
            ->groupBy('gri.product_id', 'products.name', 'gr.vendor_id', 'vendors.name')
            ->orderBy('products.name')
            ->orderBy('avg_price')
            ->get();

        return [
            'price_trend' => $priceTrend,
            'vendor_comparison' => $vendorComparison,
        ];
    }
}
