<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Controllers\Api\Helpers\RestaurantBranchFilterTrait;
use App\Models\Inventory;
use App\Models\InventoryTransaction;
use App\Models\Branch;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class InventoryReportController extends Controller
{
    use RestaurantBranchFilterTrait;

    public function __construct()
    {
        $this->middleware('auth:sanctum');
    }

    /**
     * Get current stock report
     * Calculates current stock by summing In transactions and subtracting Out transactions from inventories table
     */
    public function currentStock(Request $request)
    {
        $user = $request->user();

        // Build query for inventories table directly
        $inventoryQuery = Inventory::query()
            ->select(
                'inventories.item_id',
                'inventories.branch_id',
                DB::raw('SUM(CASE WHEN transaction_type = "in" THEN quantity ELSE 0 END) as total_in'),
                DB::raw('SUM(CASE WHEN transaction_type = "out" THEN quantity ELSE 0 END) as total_out'),
                DB::raw('SUM(CASE WHEN transaction_type = "in" THEN quantity ELSE 0 END) - SUM(CASE WHEN transaction_type = "out" THEN quantity ELSE 0 END) as current_stock')
            )
            ->groupBy('inventories.item_id', 'inventories.branch_id');

        // Apply restaurant/branch filtering
        $this->applyRestaurantBranchFilter($inventoryQuery, $user, $request);

        // Date filters - filter the inventories that contribute to stock calculation
        if ($request->has('date_from')) {
            $inventoryQuery->whereDate('inventories.created_at', '>=', $request->date_from);
        }

        if ($request->has('date_to')) {
            $inventoryQuery->whereDate('inventories.created_at', '<=', $request->date_to);
        }

        // "As of" date - show cumulative stock up to that date
        if ($request->has('as_of_date') && !$request->has('date_from') && !$request->has('date_to')) {
            $inventoryQuery->whereDate('inventories.created_at', '<=', $request->as_of_date);
        }

        // Type filter - filter by transaction_type (in/out)
        if ($request->has('type') && in_array($request->type, ['in', 'out'])) {
            $inventoryQuery->where('inventories.transaction_type', $request->type);
        }

        // Additional filters
        if ($request->has('category_id')) {
            $inventoryQuery->where('inventories.category_id', $request->category_id);
        }

        if ($request->has('item_id')) {
            $inventoryQuery->where('inventories.item_id', $request->item_id);
        }

        // Item search
        if ($request->has('search') && $request->search) {
            $searchTerm = $request->search;
            $inventoryQuery->where(function($query) use ($searchTerm) {
                $query->where('inventories.item_name', 'like', '%' . $searchTerm . '%')
                      ->orWhereHas('item', function($q) use ($searchTerm) {
                          $q->where('name', 'like', '%' . $searchTerm . '%');
                      })
                      ->orWhere('inventories.category', 'like', '%' . $searchTerm . '%');
            });
        }

        // Get aggregated or per-branch view
        $aggregated = $request->get('aggregated', false);
        if ($aggregated) {
            // Aggregate across all branches
            $inventoryQuery->groupBy('inventories.item_id');
        }

        if ($aggregated) {
            // Aggregate across all branches
            $inventoryQuery->groupBy('inventories.item_id');
        }

        // Get all stock data first (before pagination)
        $stockData = $inventoryQuery->get();

        // Load item details (get first inventory record for each item to get details)
        $itemIds = $stockData->pluck('item_id')->unique();
        $inventories = Inventory::whereIn('item_id', $itemIds)
            ->with(['item', 'branch', 'restaurant'])
            ->select('item_id', 'item_name', 'category_id', 'category', 'item_unit', 'unit_price', 'branch_id')
            ->distinct()
            ->get()
            ->groupBy('item_id')
            ->map(function ($group) {
                return $group->first();
            });

        // Combine stock data with inventory details
        $result = $stockData->map(function ($stock) use ($inventories, $aggregated) {
            $inventory = $inventories->get($stock->item_id);
            if (!$inventory) {
                return null;
            }

            // Get branch name if not aggregated
            $branchName = null;
            if (!$aggregated && $stock->branch_id) {
                $branch = Branch::find($stock->branch_id);
                $branchName = $branch ? $branch->name : null;
            }

            return [
                'item_id' => $stock->item_id,
                'item_name' => $inventory->item_name,
                'category_id' => $inventory->category_id,
                'category' => $inventory->category,
                'item_unit' => $inventory->item_unit,
                'unit_price' => $inventory->unit_price,
                'branch_id' => $aggregated ? null : $stock->branch_id,
                'branch_name' => $branchName,
                'total_in' => round($stock->total_in, 2),
                'total_out' => round($stock->total_out, 2),
                'current_stock' => round($stock->current_stock, 2),
                'total_value' => round($stock->current_stock * $inventory->unit_price, 2),
            ];
        })->filter();

        // Apply pagination
        $perPage = $request->get('per_page', 50);
        $page = $request->get('page', 1);
        $total = $result->count();
        $lastPage = ceil($total / $perPage);
        
        // Slice the result for pagination
        $paginatedResult = $result->values()->slice(($page - 1) * $perPage, $perPage);

        return response()->json([
            'data' => $paginatedResult,
            'current_page' => (int) $page,
            'last_page' => $lastPage,
            'per_page' => (int) $perPage,
            'total' => $total,
            'aggregated' => $aggregated,
        ]);
    }

    /**
     * Get daily transaction report
     */
    public function dailyReport(Request $request)
    {
        $user = $request->user();

        // Support both single date and date range
        $date = $request->get('date');
        $dateFrom = $request->get('date_from');
        $dateTo = $request->get('date_to');

        // Validate: either date or date_from/date_to
        if (!$date && !$dateFrom && !$dateTo) {
            // Default to today if no date provided
            $date = now()->toDateString();
        }

        $query = InventoryTransaction::with(['inventory.item', 'inventory.category', 'branch', 'creator']);

        // Apply date filter
        if ($date) {
            $query->whereDate('created_at', $date);
        } else {
            if ($dateFrom) {
                $query->whereDate('created_at', '>=', $dateFrom);
            }
            if ($dateTo) {
                $query->whereDate('created_at', '<=', $dateTo);
            }
        }

        // Apply restaurant/branch filtering
        $this->applyRestaurantBranchFilter($query, $user, $request);

        // Type filter (IN/OUT)
        if ($request->has('type') && in_array($request->type, ['in', 'out'])) {
            $query->where('type', $request->type);
        }

        // Category filter
        if ($request->has('category_id') && $request->category_id) {
            $query->whereHas('inventory', function ($q) use ($request) {
                $q->where('category_id', $request->category_id);
            });
        }

        // Item search
        if ($request->has('search') && $request->search) {
            $searchTerm = $request->search;
            $query->whereHas('inventory', function($q) use ($searchTerm) {
                $q->where('item_name', 'like', '%' . $searchTerm . '%')
                  ->orWhereHas('item', function($itemQuery) use ($searchTerm) {
                      $itemQuery->where('name', 'like', '%' . $searchTerm . '%');
                  });
            });
        }

        // Get all transactions for summary calculation
        $allTransactions = $query->orderBy('created_at', 'desc')->get();

        // Calculate summary from all transactions
        $summary = [
            'total_in' => $allTransactions->where('type', 'in')->sum('quantity'),
            'total_out' => $allTransactions->where('type', 'out')->sum('quantity'),
            'net_change' => $allTransactions->where('type', 'in')->sum('quantity') - $allTransactions->where('type', 'out')->sum('quantity'),
            'total_in_value' => $allTransactions->where('type', 'in')->sum('total_amount'),
            'total_out_value' => $allTransactions->where('type', 'out')->sum('total_amount'),
            'net_value_change' => $allTransactions->where('type', 'in')->sum('total_amount') - $allTransactions->where('type', 'out')->sum('total_amount'),
        ];

        // Apply pagination
        $perPage = $request->get('per_page', 50);
        $transactions = $query->orderBy('created_at', 'desc')->paginate($perPage);

        return response()->json([
            'date' => $date,
            'date_from' => $dateFrom,
            'date_to' => $dateTo,
            'summary' => $summary,
            'data' => $transactions->items(),
            'current_page' => $transactions->currentPage(),
            'last_page' => $transactions->lastPage(),
            'per_page' => $transactions->perPage(),
            'total' => $transactions->total(),
        ]);
    }

    /**
     * Get transaction history with pagination
     */
    public function transactionHistory(Request $request)
    {
        $user = $request->user();

        $query = InventoryTransaction::with(['inventory.item', 'inventory.category', 'branch', 'creator', 'restaurant']);

        // Apply restaurant/branch filtering
        $this->applyRestaurantBranchFilter($query, $user, $request);

        // Additional filters
        if ($request->has('inventory_id')) {
            $query->where('inventory_id', $request->inventory_id);
        }

        if ($request->has('type')) {
            $query->where('type', $request->type);
        }

        if ($request->has('date_from')) {
            $query->whereDate('created_at', '>=', $request->date_from);
        }

        if ($request->has('date_to')) {
            $query->whereDate('created_at', '<=', $request->date_to);
        }

        if ($request->has('batch_id') && $request->batch_id) {
            $query->where('batch_id', $request->batch_id);
        }

        // Category filter
        if ($request->has('category_id') && $request->category_id) {
            $query->whereHas('inventory', function ($q) use ($request) {
                $q->where('category_id', $request->category_id);
            });
        }

        // Search (item name or batch ID)
        if ($request->has('search') && $request->search) {
            $searchTerm = $request->search;
            $query->where(function ($q) use ($searchTerm) {
                $q->whereHas('inventory', function ($inv) use ($searchTerm) {
                    $inv->where('item_name', 'like', '%' . $searchTerm . '%');
                })->orWhere('batch_id', 'like', '%' . $searchTerm . '%');
            });
        }

        $transactions = $query->orderBy('created_at', 'desc')
            ->paginate($request->get('per_page', 50));

        return response()->json($transactions);
    }
}
