<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Product;
use Dompdf\Dompdf;
use Dompdf\Options;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;
use Symfony\Component\HttpFoundation\StreamedResponse;

class InventoryReportController extends Controller
{
    public function index(Request $request): View
    {
        $totalProducts = Product::count();
        $totalValue = Product::sum(DB::raw('stock * purchase_price'));
        $lowStockCount = Product::whereColumn('stock', '<=', 'alert_quantity')->where('stock', '>', 0)->count();
        $outOfStockCount = Product::where('stock', 0)->count();

        return view('admin.reports.inventory.index', [
            'totalProducts' => $totalProducts,
            'totalValue' => $totalValue,
            'lowStockCount' => $lowStockCount,
            'outOfStockCount' => $outOfStockCount,
        ]);
    }

    /**
     * API endpoint to fetch inventory data
     */
    public function getInventoryData(Request $request): JsonResponse
    {
        $search = $request->get('search');
        $category = $request->get('category');
        $status = $request->get('status'); // all, in_stock, low_stock, out_of_stock

        $query = Product::with(['category', 'unit']);

        if ($search) {
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                    ->orWhere('code', 'like', "%{$search}%")
                    ->orWhere('barcode', 'like', "%{$search}%");
            });
        }

        if ($category && $category !== 'all') {
            $query->where('category_id', $category);
        }

        if ($status === 'low_stock') {
            $query->whereColumn('stock', '<=', 'alert_quantity')->where('stock', '>', 0);
        } elseif ($status === 'out_of_stock') {
            $query->where('stock', 0);
        } elseif ($status === 'in_stock') {
            $query->where('stock', '>', 0)->whereColumn('stock', '>', 'alert_quantity');
        }

        $products = $query->orderBy('name', 'asc')->get()->map(function ($product) {
            $totalValue = $product->stock * $product->purchase_price;
            $status = 'in_stock';
            $statusLabel = 'In Stock';

            if ($product->stock == 0) {
                $status = 'out_of_stock';
                $statusLabel = 'Out of Stock';
            } elseif ($product->stock <= $product->alert_quantity) {
                $status = 'low_stock';
                $statusLabel = 'Low Stock';
            }

            return [
                'id' => $product->id,
                'name' => $product->name,
                'code' => $product->code ?? 'N/A',
                'category' => $product->category->name ?? 'N/A',
                'stock' => $product->stock,
                'alert_quantity' => $product->alert_quantity ?? 0,
                'unit_price' => number_format($product->purchase_price, 2),
                'total_value' => number_format($totalValue, 2),
                'status' => $status,
                'status_label' => $statusLabel,
                /** For out-of-stock report: last product update (no separate stock-movement table). */
                'last_stock_date' => $product->updated_at?->format('M d, Y') ?? '—',
            ];
        });

        // Calculate stats
        $totalProducts = Product::count();
        $totalValue = Product::sum(DB::raw('stock * purchase_price'));
        $lowStockCount = Product::whereColumn('stock', '<=', 'alert_quantity')->where('stock', '>', 0)->count();
        $outOfStockCount = Product::where('stock', 0)->count();

        return response()->json([
            'success' => true,
            'data' => $products,
            'stats' => [
                'totalProducts' => $totalProducts,
                'totalValue' => $totalValue,
                'lowStockCount' => $lowStockCount,
                'outOfStockCount' => $outOfStockCount,
            ],
        ]);
    }

    /**
     * Export inventory data to CSV
     */
    public function exportInventoryCsv(Request $request): StreamedResponse
    {
        $search = $request->get('search');
        $category = $request->get('category');
        $status = $request->get('status');

        $query = Product::with(['category', 'unit']);

        if ($search) {
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                    ->orWhere('code', 'like', "%{$search}%");
            });
        }

        if ($category && $category !== 'all') {
            $query->where('category_id', $category);
        }

        if ($status === 'low_stock') {
            $query->whereColumn('stock', '<=', 'alert_quantity')->where('stock', '>', 0);
        } elseif ($status === 'out_of_stock') {
            $query->where('stock', 0);
        }

        $products = $query->orderBy('name', 'asc')->get();

        $filename = 'inventory_report_'.now()->format('Y-m-d').'.csv';
        $headers = [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="'.$filename.'"',
        ];

        $callback = function () use ($products) {
            $file = fopen('php://output', 'w');
            fputcsv($file, ['#', 'Product', 'Category', 'Stock', 'Unit Price', 'Total Value', 'Status']);

            foreach ($products as $index => $product) {
                $totalValue = $product->stock * $product->purchase_price;
                $status = 'In Stock';
                if ($product->stock == 0) {
                    $status = 'Out of Stock';
                } elseif ($product->stock <= $product->alert_quantity) {
                    $status = 'Low Stock';
                }

                fputcsv($file, [
                    $index + 1,
                    $product->name,
                    $product->category->name ?? 'N/A',
                    $product->stock,
                    number_format($product->purchase_price, 2),
                    number_format($totalValue, 2),
                    $status,
                ]);
            }

            fclose($file);
        };

        return response()->stream($callback, 200, $headers);
    }

    /**
     * Export inventory data to PDF
     */
    public function exportInventoryPdf(Request $request)
    {
        $search = $request->get('search');
        $category = $request->get('category');
        $status = $request->get('status');

        $query = Product::with(['category', 'unit']);

        if ($search) {
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                    ->orWhere('code', 'like', "%{$search}%");
            });
        }

        if ($category && $category !== 'all') {
            $query->where('category_id', $category);
        }

        if ($status === 'low_stock') {
            $query->whereColumn('stock', '<=', 'alert_quantity')->where('stock', '>', 0);
        } elseif ($status === 'out_of_stock') {
            $query->where('stock', 0);
        }

        $products = $query->orderBy('name', 'asc')->get();
        $totalValue = $products->sum(function ($product) {
            return $product->stock * $product->purchase_price;
        });

        $html = view('admin.reports.inventory.inventory-pdf', [
            'products' => $products,
            'totalValue' => $totalValue,
        ])->render();

        $options = new Options;
        $options->set('isHtml5ParserEnabled', true);
        $options->set('isRemoteEnabled', true);
        $options->set('defaultFont', 'Arial');

        $dompdf = new Dompdf($options);
        $dompdf->loadHtml($html);
        $dompdf->setPaper('A4', 'landscape');
        $dompdf->render();

        $filename = 'inventory_report_'.now()->format('Y-m-d').'.pdf';

        return $dompdf->stream($filename);
    }
}
