<?php
namespace App\Http\Controllers;
use App\Models as M;
use App\Services\SequenceService;
use App\Services\StockService;
use App\Support\CrudRegistry;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
class ProductionEntryController extends Controller {
    public function index(Request $r) { return app(CrudController::class)->index($r, 'production-entries'); }
    public function show(int $id) { return app(CrudController::class)->show('production-entries', $id); }
    public function create() {
        $this->need('production.create');
        return view('docs.production.form', $this->formData(new M\ProductionEntry(['entry_date' => date('Y-m-d'), 'shift' => 'day'])));
    }
    public function store(Request $r) {
        $this->need('production.create');
        $d = $r->validate(['entry_date' => 'required|date', 'shift' => 'required|in:day,night', 'quarry_id' => 'required|exists:quarries,id',
            'crusher_line_id' => 'required|exists:crusher_lines,id', 'product_id' => 'required|exists:products,id',
            'produced_tonnes' => 'required|numeric|min:0.001', 'operating_hours' => 'nullable|numeric', 'downtime_hours' => 'nullable|numeric',
            'fuel_used_litres' => 'nullable|numeric', 'operator_name' => 'nullable|max:100', 'remarks' => 'nullable']);
        $d['entry_no'] = SequenceService::next('production_entry');
        $d['status'] = 'draft'; $d['created_by'] = Auth::id();
        $e = M\ProductionEntry::create($d);
        return redirect()->route('production-entries.show', $e)->with('success', 'Production entry '.$e->entry_no.' saved as draft.');
    }
    public function edit(int $id) {
        $this->need('production.edit');
        $e = M\ProductionEntry::findOrFail($id);
        abort_unless($e->status === 'draft', 403, 'Only drafts can be edited.');
        return view('docs.production.form', $this->formData($e));
    }
    public function update(Request $r, int $id) {
        $this->need('production.edit');
        $e = M\ProductionEntry::findOrFail($id);
        abort_unless($e->status === 'draft', 403, 'Only drafts can be edited.');
        $d = $r->validate(['entry_date' => 'required|date', 'shift' => 'required|in:day,night', 'quarry_id' => 'required|exists:quarries,id',
            'crusher_line_id' => 'required|exists:crusher_lines,id', 'product_id' => 'required|exists:products,id',
            'produced_tonnes' => 'required|numeric|min:0.001', 'operating_hours' => 'nullable|numeric', 'downtime_hours' => 'nullable|numeric',
            'fuel_used_litres' => 'nullable|numeric', 'operator_name' => 'nullable|max:100', 'remarks' => 'nullable']);
        $e->update($d);
        return redirect()->route('production-entries.show', $e)->with('success', 'Production entry updated.');
    }
    public function destroy(int $id) {
        $this->need('production.delete');
        $e = M\ProductionEntry::findOrFail($id);
        abort_unless($e->status === 'draft', 403, 'Only drafts can be deleted.');
        $e->delete();
        return redirect()->route('production-entries.index')->with('success', 'Entry deleted.');
    }
    public function approve(int $id) {
        $this->need('production.approve');
        $e = M\ProductionEntry::findOrFail($id);
        abort_unless($e->status === 'draft', 403, 'Only drafts can be approved.');
        DB::transaction(function () use ($e) {
            $pile = StockService::stockpileFor($e->quarry_id, $e->product_id);
            StockService::moveStockpile($pile->id, $e->entry_date->format('Y-m-d'), 'production-in', $e->produced_tonnes, 0, 'production_entry', $e->id, 'Production '.$e->entry_no);
            $e->update(['status' => 'approved', 'approved_by' => Auth::id()]);
        });
        return back()->with('success', 'Production approved & posted to stockpile.');
    }
    protected function formData(M\ProductionEntry $e): array {
        return ['record' => $e, 'isNew' => !$e->exists, 'cfg' => CrudRegistry::get('production-entries'), 'key' => 'production-entries',
            'entryNo' => $e->exists ? $e->entry_no : SequenceService::peek('production_entry'),
            'quarries' => M\Quarry::orderBy('name')->get(), 'lines' => M\CrusherLine::orderBy('code')->get(), 'products' => M\Product::where('is_active', true)->orderBy('name')->get()];
    }
}
