<?php

namespace App\Http\Controllers;

use App\ControlAccount;
use App\MeasurementUnit;
use App\ServiceVoucher;
use App\Suppliers;
use App\Purchaser;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class ServiceVoucherController extends Controller
{
    protected string $module = 'Service Vouchers';

    public function __construct()
    {
        $module = $this->module;
        $this->middleware("permission:$module list")->only(['index']);
        $this->middleware("permission:$module view")->only(['show']);
        $this->middleware("permission:$module add")->only(['create', 'store']);
        $this->middleware("permission:$module edit")->only(['edit', 'update']);
        $this->middleware("permission:$module delete")->only(['destroy']);
    }

    /**
     * Build merged party list for dropdowns.
     * Each item: ['type' => 'Supplier'|'Purchaser', 'id' => int, 'display_name' => string]
     */
    private function getMergedParties(): array
    {
        $suppliers = Suppliers::where('status', 1)->get()->map(fn($s) => [
            'type'         => 'Supplier',
            'id'           => $s->id_supplier,
            'display_name' => $s->supplier_name_urdu ?? $s->supplier_name,
        ]);

        $purchasers = Purchaser::where('status', 1)->get()->map(fn($p) => [
            'type'         => 'Purchaser',
            'id'           => $p->id_purchaser,
            'display_name' => $p->purchaser_name_urdu ?? $p->purchaser_name,
        ]);

        return $suppliers->merge($purchasers)->sortBy('display_name')->values()->toArray();
    }

    public function index()
    {
        $vouchers = ServiceVoucher::with('details', 'details.controlAccount')->get();
        return view('service_vouchers.index', compact('vouchers'));
    }

    public function create()
    {
        $parties  = $this->getMergedParties();
        $accounts = ControlAccount::where('main_account_id', 4)->get();
        $units    = MeasurementUnit::where('measurement_unit_status', '1')->get();
        return view('service_vouchers.create', compact('parties', 'accounts', 'units'));
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'party_type'                   => 'required|in:Supplier,Purchaser',
            'party_id'                     => 'required|integer|min:1',
            'voucher_date'                 => 'required|date',
            'truck_no'                     => 'nullable|string|max:50',
            'bill_no'                      => 'nullable|string|max:50',
            'description'                  => 'nullable|string',
            'details'                      => 'required|array|min:1',
            'details.*.control_account_id' => 'required|integer',
            'details.*.qty'                => 'required|numeric|min:0.01',
            'details.*.unit'               => 'required|string|min:1',
            'details.*.price'              => 'required|numeric|min:0',
            'details.*.narration'          => 'nullable|string',
        ]);

        DB::transaction(function () use ($validated) {
            $lastId      = (ServiceVoucher::max('id') ?? 0) + 1;
            $voucherNo   = 'SV-' . date('Y') . '-' . str_pad($lastId, 5, '0', STR_PAD_LEFT);
            $totalAmount = collect($validated['details'])->sum(fn($d) => $d['qty'] * $d['price']);

            $voucher = ServiceVoucher::create([
                'voucher_no'   => $voucherNo,
                'voucher_date' => $validated['voucher_date'],
                'truck_no'     => $validated['truck_no']    ?? null,
                'bill_no'      => $validated['bill_no']     ?? null,
                'party_type'   => $validated['party_type'], // 'Supplier' or 'Purchaser'
                'party_id'     => $validated['party_id'],   // actual model PK
                'total_amount' => $totalAmount,
                'description'  => $validated['description'] ?? null,
            ]);

            foreach ($validated['details'] as $row) {
                $voucher->details()->create([
                    'control_account_id' => $row['control_account_id'],
                    'qty'                => $row['qty'],
                    'unit'               => $row['unit'],
                    'price'              => $row['price'],
                    'amount'             => $row['qty'] * $row['price'],
                    'narration'          => $row['narration'] ?? null,
                ]);
            }
        });

        return redirect(route('service_vouchers.index'))
            ->with('success', 'Service Voucher Created Successfully');
    }

    public function edit($id)
    {
        $id      = decrypt($id);
        $voucher = ServiceVoucher::with('details')->findOrFail($id);
        $parties  = $this->getMergedParties();
        $accounts = ControlAccount::all();
        $units    = MeasurementUnit::all();
        return view('service_vouchers.edit', compact('voucher', 'parties', 'accounts', 'units'));
    }

    public function update(Request $request, $id)
    {
        $id      = decrypt($id);
        $voucher = ServiceVoucher::findOrFail($id);

        $validated = $request->validate([
            'party_type'                   => 'required|in:Supplier,Purchaser',
            'party_id'                     => 'required|integer|min:1',
            'voucher_date'                 => 'required|date',
            'truck_no'                     => 'nullable|string|max:50',
            'bill_no'                      => 'nullable|string|max:50',
            'description'                  => 'nullable|string',
            'details'                      => 'required|array|min:1',
            'details.*.control_account_id' => 'required|integer',
            'details.*.qty'                => 'required|numeric|min:0.01',
            'details.*.unit'               => 'required|string|min:1',
            'details.*.price'              => 'required|numeric|min:0',
            'details.*.narration'          => 'nullable|string',
        ]);

        DB::transaction(function () use ($validated, $voucher) {
            $totalAmount = collect($validated['details'])->sum(fn($d) => $d['qty'] * $d['price']);

            $voucher->update([
                'voucher_date' => $validated['voucher_date'],
                'truck_no'     => $validated['truck_no']    ?? null,
                'bill_no'      => $validated['bill_no']     ?? null,
                'party_type'   => $validated['party_type'],
                'party_id'     => $validated['party_id'],
                'total_amount' => $totalAmount,
                'description'  => $validated['description'] ?? null,
            ]);

            $voucher->details()->delete();

            foreach ($validated['details'] as $row) {
                $voucher->details()->create([
                    'control_account_id' => $row['control_account_id'],
                    'qty'                => $row['qty'],
                    'unit'               => $row['unit'],
                    'price'              => $row['price'],
                    'amount'             => $row['qty'] * $row['price'],
                    'narration'          => $row['narration'] ?? null,
                ]);
            }
        });

        return redirect(route('service_vouchers.index'))
            ->with('alert', 'Service Voucher Updated Successfully')
            ->with('alert-class', 'success');
    }

    public function destroy($id)
    {
        $id = decrypt($id);
        ServiceVoucher::findOrFail($id)->delete();
        return redirect()->route('service_vouchers.index')->with('success', 'Voucher Deleted');
    }
}
