<?php

namespace App\Http\Controllers\Transaction;

use App\Http\Controllers\Controller;
use App\Models\StockOpname;
use App\Models\StockOpnameDetail;
use App\Models\Product;
use App\Models\ProductStock;
use App\Models\Branch;
use App\Models\StockMovement;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;

class StockOpnameController extends Controller
{
    public function __construct()
    {
        $this->middleware(['permission:stock-opnames.index'])->only('index','show');
        $this->middleware(['permission:stock-opnames.create'])->only(['create', 'save']);
        $this->middleware(['permission:stock-opnames.edit'])->only(['edit', 'update']);
        $this->middleware(['permission:stock-opnames.delete'])->only('delete');
    }

    /**
     * Display a listing of stock opnames
     */
    public function index()
    {
        $title = "stock_opname";
        $stockOpnames = StockOpname::with(['branch', 'user'])
            ->orderBy('id', 'desc')
            ->get();

        return view('transaction.stock-opname.index', compact('title', 'stockOpnames'));
    }

    /**
     * Show the form for creating a new stock opname
     */
    public function create()
    {
        $title = "stock_opname";
        $branches = Branch::where('is_active', true)->get();

        // Generate opname number
        $opnameNumber = $this->generateOpnameNumber();

        return view('transaction.stock-opname.create', compact('title', 'branches', 'opnameNumber'));
    }

    /**
     * Get products with stock for a specific branch
     */
    public function getProductsByBranch(Request $request)
    {
        $branchId = $request->branch_id;

        $products = ProductStock::with(['product.brand', 'product.category'])
            ->where('branch_id', $branchId)
            ->get()
            ->map(function ($stock) {
                return [
                    'id' => $stock->product->id,
                    'name' => $stock->product->name,
                    'brand' => $stock->product->brand->name,
                    'unit' => $stock->product->unit,
                    'system_stock' => $stock->quantity,
                ];
            });

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

    /**
     * Store a newly created stock opname
     */
    public function save(Request $request)
    {
        $this->validate($request, [
            'branch_id' => 'required|exists:branches,id',
            'opname_date' => 'required|date',
            'details' => 'required|array|min:1',
            'details.*.product_id' => 'required|exists:products,id',
            'details.*.system_stock' => 'required|numeric|min:0',
            'details.*.physical_stock' => 'required|numeric|min:0',
        ]);

        DB::beginTransaction();
        try {
            // Create stock opname
            $stockOpname = StockOpname::create([
                'opname_number' => $this->generateOpnameNumber(),
                'branch_id' => $request->branch_id,
                'opname_date' => $request->opname_date,
                'status' => 'completed',
                'notes' => $request->notes,
                'user_id' => Auth::id(),
            ]);

            // Create stock opname details and adjust stock
            foreach ($request->details as $detail) {
                $systemStock = $detail['system_stock'];
                $physicalStock = $detail['physical_stock'];
                $difference = $physicalStock - $systemStock;

                // Skip if no difference
                if ($difference == 0) {
                    continue;
                }

                // Create opname detail
                StockOpnameDetail::create([
                    'stock_opname_id' => $stockOpname->id,
                    'product_id' => $detail['product_id'],
                    'system_stock' => $systemStock,
                    'physical_stock' => $physicalStock,
                    'difference' => $difference,
                    'notes' => $detail['notes'] ?? null,
                ]);

                // Update product stock
                $productStock = ProductStock::where('product_id', $detail['product_id'])
                    ->where('branch_id', $request->branch_id)
                    ->first();

                if ($productStock) {
                    $productStock->update(['quantity' => $physicalStock]);
                }

                // Create stock movement record
                StockMovement::create([
                    'product_id' => $detail['product_id'],
                    'branch_id' => $request->branch_id,
                    'type' => 'adjustment',
                    'quantity' => abs($difference),
                    'reference_type' => 'App\Models\StockOpname',
                    'reference_id' => $stockOpname->id,
                    'notes' => 'Stock Opname #' . $stockOpname->opname_number . ' (' . ($difference > 0 ? '+' : '') . $difference . ')',
                    'user_id' => Auth::id(),
                ]);
            }

            DB::commit();

            return redirect()->route('stock-opname')
                ->with(['success' => 'Stock Opname Berhasil Disimpan!']);

        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->back()
                ->with(['error' => 'Terjadi kesalahan: ' . $e->getMessage()])
                ->withInput();
        }
    }

    /**
     * Display the specified stock opname
     */
    public function show(StockOpname $stockOpname)
    {
        $title = "stock_opname";
        $stockOpname->load(['branch', 'user', 'stockOpnameDetails.product']);

        return view('transaction.stock-opname.show', compact('title', 'stockOpname'));
    }

    /**
     * Show the form for editing the specified stock opname
     */
    public function edit(StockOpname $stockOpname)
    {
        // Only allow editing if status is pending
        // if ($stockOpname->status !== 'pending') {
        //     return redirect()->route('stock-opname')
        //         ->with(['error' => 'Hanya stock opname dengan status pending yang dapat diubah!']);
        // }

        $title = "stock_opname";
        $branches = Branch::where('is_active', true)->get();
        $stockOpname->load(['stockOpnameDetails.product']);

        return view('transaction.stock-opname.edit', compact('title', 'stockOpname', 'branches'));
    }

    /**
     * Update the specified stock opname
     */
    public function update(Request $request, StockOpname $stockOpname)
    {
        // Only allow editing if status is pending
        // if ($stockOpname->status !== 'pending') {
        //     return redirect()->route('stock-opname')
        //         ->with(['error' => 'Hanya stock opname dengan status pending yang dapat diubah!']);
        // }

        $this->validate($request, [
            'branch_id' => 'required|exists:branches,id',
            'opname_date' => 'required|date',
            'details' => 'required|array|min:1',
            'details.*.product_id' => 'required|exists:products,id',
            'details.*.system_stock' => 'required|numeric|min:0',
            'details.*.physical_stock' => 'required|numeric|min:0',
        ]);

        DB::beginTransaction();
        try {
            // Update stock opname
            $stockOpname->update([
                'branch_id' => $request->branch_id,
                'opname_date' => $request->opname_date,
                'notes' => $request->notes,
            ]);

            // Delete old details
            $stockOpname->stockOpnameDetails()->delete();

            // Create new details
            foreach ($request->details as $detail) {
                $systemStock = $detail['system_stock'];
                $physicalStock = $detail['physical_stock'];
                $difference = $physicalStock - $systemStock;

                if ($difference == 0) {
                    continue;
                }

                StockOpnameDetail::create([
                    'stock_opname_id' => $stockOpname->id,
                    'product_id' => $detail['product_id'],
                    'system_stock' => $systemStock,
                    'physical_stock' => $physicalStock,
                    'difference' => $difference,
                    'notes' => $detail['notes'] ?? null,
                ]);
            }

            DB::commit();

            return redirect()->route('stock-opname')
                ->with(['success' => 'Stock Opname Berhasil Diupdate!']);

        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->back()
                ->with(['error' => 'Terjadi kesalahan: ' . $e->getMessage()])
                ->withInput();
        }
    }

    /**
     * Remove the specified stock opname
     */
    public function delete(StockOpname $stockOpname)
    {
        // Only allow deleting if status is pending
        // if ($stockOpname->status !== 'pending') {
        //     return redirect()->route('stock-opname')
        //         ->with(['error' => 'Hanya stock opname dengan status pending yang dapat dihapus!']);
        // }

        DB::beginTransaction();
        try {
            // Delete stock opname details
            $stockOpname->stockOpnameDetails()->delete();

            // Delete stock opname
            $stockOpname->delete();

            DB::commit();

            return redirect()->route('stock-opname')
                ->with('success', 'Stock Opname Berhasil Dihapus');

        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->route('stock-opname')
                ->with(['error' => 'Terjadi kesalahan: ' . $e->getMessage()]);
        }
    }

    /**
     * Generate unique opname number
     */
    private function generateOpnameNumber()
    {
        $prefix = 'OP';
        $date = date('Ymd');
        $lastOpname = StockOpname::whereDate('created_at', today())
            ->orderBy('id', 'desc')
            ->first();

        if ($lastOpname) {
            $lastNumber = intval(substr($lastOpname->opname_number, -4));
            $newNumber = $lastNumber + 1;
        } else {
            $newNumber = 1;
        }

        return $prefix . $date . str_pad($newNumber, 4, '0', STR_PAD_LEFT);
    }
}
