<?php
namespace App\Http\Controllers;
use App\Models as M;
use App\Services\ApprovalService;
use App\Services\GhanaTaxService;
use App\Services\SequenceService;
use App\Support\CrudRegistry;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
class ClientIpcController extends Controller {
    public function index(Request $r) { return app(CrudController::class)->index($r, 'client-ipcs'); }
    public function show(int $id) { return app(CrudController::class)->show('client-ipcs', $id); }
    public function create() {
        $this->need('projects.create');
        return view('docs.client-ipc.form', $this->formData(new M\ClientIpc(['ipc_date' => date('Y-m-d')])));
    }
    public function store(Request $r) {
        $this->need('projects.create');
        $d = $this->validated($r);
        $ipc = DB::transaction(function () use ($d) {
            $p = M\Project::find($d['project_id']);
            $d['ipc_no'] = SequenceService::next('client_ipc');
            $d['status'] = 'submitted';
            $d['retention_deducted'] = round($d['gross_valuation'] * ($p->retention_percent ?? 0) / 100, 2);
            $d['tax_withheld'] = $d['tax_withheld'] ?? GhanaTaxService::withholding($d['gross_valuation'], 'services');
            $d['net_certified'] = round($d['gross_valuation'] - $d['retention_deducted'] - ($d['advance_repayment'] ?? 0) - $d['tax_withheld'], 2);
            $ipc = M\ClientIpc::create($d);
            ApprovalService::request('client_ipc', $ipc->id, $ipc->ipc_no);
            return $ipc;
        });
        return redirect()->route('client-ipcs.show', $ipc)->with('success', 'IPC '.$ipc->ipc_no.' submitted.');
    }
    public function edit(int $id) {
        $this->need('projects.edit');
        $ipc = M\ClientIpc::findOrFail($id);
        abort_unless(in_array($ipc->status, ['draft', 'submitted']), 403, 'Certified IPCs cannot be edited.');
        return view('docs.client-ipc.form', $this->formData($ipc));
    }
    public function update(Request $r, int $id) {
        $this->need('projects.edit');
        $ipc = M\ClientIpc::findOrFail($id);
        abort_unless(in_array($ipc->status, ['draft', 'submitted']), 403, 'Certified IPCs cannot be edited.');
        $d = $this->validated($r);
        $p = M\Project::find($d['project_id']);
        $d['retention_deducted'] = round($d['gross_valuation'] * ($p->retention_percent ?? 0) / 100, 2);
        $d['tax_withheld'] = $d['tax_withheld'] ?? GhanaTaxService::withholding($d['gross_valuation'], 'services');
        $d['net_certified'] = round($d['gross_valuation'] - $d['retention_deducted'] - ($d['advance_repayment'] ?? 0) - $d['tax_withheld'], 2);
        $ipc->update($d);
        return redirect()->route('client-ipcs.show', $ipc)->with('success', 'IPC updated.');
    }
    public function destroy(int $id) {
        $this->need('projects.delete');
        $ipc = M\ClientIpc::findOrFail($id);
        abort_unless(in_array($ipc->status, ['draft', 'submitted']), 403, 'Certified IPCs cannot be deleted.');
        $ipc->delete();
        return redirect()->route('client-ipcs.index')->with('success', 'IPC deleted.');
    }
    /** Called after certification: raises a draft sales invoice to the project client. */
    public function postCertify(M\ClientIpc $ipc): void {
        $p = M\Project::find($ipc->project_id);
        if (!$p?->client_id || $ipc->net_certified <= 0) return;
        $exists = M\SalesInvoice::where('reference_ipc', $ipc->id)->exists();
        if ($exists) return;
        try {
            $inv = M\SalesInvoice::create(['invoice_no' => SequenceService::next('sales_invoice'), 'invoice_date' => $ipc->ipc_date->format('Y-m-d'),
                'due_date' => $ipc->ipc_date->copy()->addDays(30)->format('Y-m-d'), 'customer_id' => $p->client_id, 'reference_ipc' => $ipc->id, 'subtotal' => $ipc->net_certified,
                'discount_amount' => 0, 'levy_nhil' => 0, 'levy_getfund' => 0, 'levy_covid' => 0, 'vat_amount' => 0,
                'grand_total' => $ipc->net_certified, 'amount_paid' => 0, 'balance_due' => $ipc->net_certified,
                'status' => 'draft', 'terms' => 'IPC '.$ipc->ipc_no.' — '.$p->name, 'created_by' => Auth::id() ?? 1]);
            $inv->lines()->create(['description' => 'IPC '.$ipc->ipc_no.' — '.$p->name.' (certified works)', 'qty' => 1, 'rate' => $ipc->net_certified, 'amount' => $ipc->net_certified]);
        } catch (\Throwable $e) {}
    }
    protected function validated(Request $r): array {
        return $r->validate(['project_id' => 'required|exists:projects,id', 'ipc_date' => 'required|date',
            'period_from' => 'nullable|date', 'period_to' => 'nullable|date', 'gross_valuation' => 'required|numeric|min:0.01',
            'advance_repayment' => 'nullable|numeric|min:0', 'tax_withheld' => 'nullable|numeric|min:0', 'remarks' => 'nullable|max:500']);
    }
    protected function formData(M\ClientIpc $ipc): array {
        return ['record' => $ipc, 'isNew' => !$ipc->exists, 'cfg' => CrudRegistry::get('client-ipcs'), 'key' => 'client-ipcs',
            'docNo' => $ipc->exists ? $ipc->ipc_no : SequenceService::peek('client_ipc'),
            'projects' => M\Project::orderBy('code')->get()];
    }
}
