<?php

namespace App\Http\Controllers;

use App\Models\Expense;
use App\Models\ExpenseCategory;
use App\Models\Material;
use App\Models\Purchase;
use App\Models\PurchasePayment;
use App\Models\Supplier;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;

class PurchaseController extends Controller
{
    public function index(Request $request)
    {
        $query = Purchase::with(['material', 'creator', 'supplierRelation']);

        if ($request->filled('material_id')) {
            $query->where('material_id', $request->material_id);
        }

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

        if ($request->filled('payment_status')) {
            $query->where('payment_status', $request->payment_status);
        }

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

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

        $purchases = $query->latest()->paginate(15)->withQueryString();
        $materials = Material::active()->orderBy('name')->get();

        return view('pages.purchases.index', [
            'title' => 'Pembelian Stok',
            'purchases' => $purchases,
            'materials' => $materials,
            'types' => Purchase::TYPES,
            'paymentStatuses' => Purchase::PAYMENT_STATUSES,
        ]);
    }

    public function create()
    {
        $materials = Material::active()->orderBy('name')->get();
        $suppliers = Supplier::active()->orderBy('name')->get();

        return view('pages.purchases.form', [
            'title' => 'Tambah Pembelian Stok',
            'purchase' => new Purchase(),
            'materials' => $materials,
            'suppliers' => $suppliers,
            'types' => Purchase::TYPES,
        ]);
    }

    public function store(Request $request)
    {
        $request->merge([
            'unit_price' => str_replace('.', '', $request->unit_price ?? '0'),
            'total_price' => str_replace('.', '', $request->total_price ?? '0'),
            'initial_payment' => str_replace('.', '', $request->initial_payment ?? '0'),
            'quantity' => str_replace(',', '.', $request->quantity ?? '0'),
        ]);

        $validated = $request->validate([
            'material_id' => 'required|exists:materials,id',
            'purchase_date' => 'required|date',
            'quantity' => 'required|numeric|min:0.01',
            'unit_price' => 'required|numeric|min:0',
            'total_price' => 'required|numeric|min:0',
            'type' => 'required|in:satuan,meteran',
            'supplier_id' => 'nullable|exists:suppliers,id',
            'notes' => 'nullable|string|max:500',
            'payment_type' => 'required|in:full,dp',
            'initial_payment' => 'nullable|numeric|min:0',
            'payment_proof' => 'nullable|image|max:2048',
        ]);

        $validated['created_by'] = Auth::id();

        $initialPayment = (float) ($validated['initial_payment'] ?? 0);
        $totalPrice = (float) $validated['total_price'];

        if ($validated['payment_type'] === 'full' || $initialPayment >= $totalPrice) {
            $validated['paid_amount'] = $totalPrice;
            $validated['payment_status'] = 'paid';
            $initialPayment = $totalPrice;
        } elseif ($initialPayment > 0) {
            $validated['paid_amount'] = $initialPayment;
            $validated['payment_status'] = 'partial';
        } else {
            $validated['paid_amount'] = 0;
            $validated['payment_status'] = 'unpaid';
        }

        unset($validated['payment_type'], $validated['initial_payment'], $validated['payment_proof']);

        DB::transaction(function () use ($request, $validated, $initialPayment, $totalPrice) {
            $purchase = Purchase::create($validated);

            if ($initialPayment > 0) {
                $paymentData = [
                    'purchase_id' => $purchase->id,
                    'amount' => $initialPayment,
                    'payment_date' => $validated['purchase_date'],
                    'notes' => $initialPayment >= $totalPrice ? 'Pembayaran lunas' : 'Pembayaran awal (DP)',
                    'created_by' => Auth::id(),
                ];

                if ($request->hasFile('payment_proof')) {
                    $paymentData['proof'] = $request->file('payment_proof')->store('purchase-proofs', 'public');
                }

                $purchasePayment = PurchasePayment::create($paymentData);

                $this->createBahanBakuExpenseFromPurchasePayment($purchase, $purchasePayment);
            }
        });

        return redirect()->route('purchases.index')
            ->with('success', 'Pembelian stok berhasil ditambahkan.');
    }

    public function show(Purchase $purchase)
    {
        $purchase->load(['material', 'creator', 'supplierRelation', 'payments.creator']);

        return view('pages.purchases.show', [
            'title' => 'Detail Pembelian',
            'purchase' => $purchase,
        ]);
    }

    public function destroy(Purchase $purchase)
    {
        DB::transaction(function () use ($purchase) {
            foreach ($purchase->payments as $payment) {
                Expense::where('description', 'like', '%purchase_payment:' . $payment->id . '%')->delete();

                if ($payment->proof) {
                    Storage::disk('public')->delete($payment->proof);
                }
            }

            $purchase->delete();
        });

        return redirect()->route('purchases.index')
            ->with('success', 'Pembelian stok berhasil dihapus.');
    }

    private function createBahanBakuExpenseFromPurchasePayment(Purchase $purchase, PurchasePayment $purchasePayment): void
    {
        $purchase->loadMissing(['material', 'supplierRelation']);

        $category = ExpenseCategory::firstOrCreate(
            ['name' => 'Bahan Baku'],
            ['is_active' => true]
        );

        $materialName = $purchase->material->name ?? 'Pembelian Bahan';
        $supplierName = $purchase->supplierRelation->name ?? $purchase->supplier ?? '-';

        $description = "purchase_payment:{$purchasePayment->id}"
            . " | purchase_id:{$purchase->id}"
            . " | Bahan Baku"
            . " | {$materialName}"
            . " | Supplier: {$supplierName}"
            . " | Pembayaran awal";

        $alreadyExists = Expense::where('description', 'like', '%purchase_payment:' . $purchasePayment->id . '%')->exists();

        if ($alreadyExists) {
            return;
        }

        Expense::create([
            'expense_category_id' => $category->id,
            'amount' => $purchasePayment->amount,
            'expense_date' => $purchasePayment->payment_date,
            'description' => $description,
            'created_by' => $purchasePayment->created_by ?? Auth::id(),
        ]);
    }
}
