<?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\DB;
class SubcontractorClaimController extends Controller {
    public function index(Request $r) { return app(CrudController::class)->index($r, 'subcontractor-claims'); }
    public function show(int $id) { return app(CrudController::class)->show('subcontractor-claims', $id); }
    public function create() {
        $this->need('projects.create');
        return view('docs.subcontractor-claim.form', $this->formData(new M\SubcontractorClaim(['claim_date' => date('Y-m-d')])));
    }
    public function store(Request $r) {
        $this->need('projects.create');
        $d = $this->validated($r);
        $c = DB::transaction(function () use ($d) {
            $sub = M\Subcontract::find($d['subcontract_id']);
            $d['project_id'] = $sub->project_id;
            $d['claim_no'] = SequenceService::next('subcontractor_claim');
            $d['status'] = 'submitted';
            $this->compute($d, (float) ($sub->retention_percent ?? 0));
            $c = M\SubcontractorClaim::create($d);
            ApprovalService::request('subcontractor_claim', $c->id, $c->claim_no);
            return $c;
        });
        return redirect()->route('subcontractor-claims.show', $c)->with('success', 'Claim '.$c->claim_no.' submitted for certification.');
    }
    public function edit(int $id) {
        $this->need('projects.edit');
        $c = M\SubcontractorClaim::findOrFail($id);
        abort_unless($c->status === 'submitted', 403, 'Certified claims cannot be edited.');
        return view('docs.subcontractor-claim.form', $this->formData($c));
    }
    public function update(Request $r, int $id) {
        $this->need('projects.edit');
        $c = M\SubcontractorClaim::findOrFail($id);
        abort_unless($c->status === 'submitted', 403, 'Certified claims cannot be edited.');
        $d = $this->validated($r);
        $sub = M\Subcontract::find($d['subcontract_id']);
        $d['project_id'] = $sub->project_id;
        $this->compute($d, (float) ($sub->retention_percent ?? 0));
        $c->update($d);
        return redirect()->route('subcontractor-claims.show', $c)->with('success', 'Claim updated.');
    }
    public function destroy(int $id) {
        $this->need('projects.delete');
        $c = M\SubcontractorClaim::findOrFail($id);
        abort_unless($c->status === 'submitted', 403, 'Certified claims cannot be deleted.');
        $c->delete();
        return redirect()->route('subcontractor-claims.index')->with('success', 'Claim deleted.');
    }
    /** Called after certification via approval inbox. */
    public function postCertify(M\SubcontractorClaim $c): void {
        $sub = M\Subcontract::find($c->subcontract_id);
        if ($sub?->supplier_id) M\Supplier::where('id', $sub->supplier_id)->increment('current_balance', $c->net_payable);
        M\ProjectExpense::create(['project_id' => $c->project_id, 'expense_date' => $c->claim_date->format('Y-m-d'), 'category' => 'subcontract',
            'description' => 'Subcontract claim '.$c->claim_no.' — '.($sub->subcontractor_name ?? ''), 'amount' => $c->net_payable, 'ref_type' => 'subcontractor_claim', 'ref_id' => $c->id]);
    }
    protected function validated(Request $r): array {
        return $r->validate(['subcontract_id' => 'required|exists:subcontracts,id', 'claim_date' => 'required|date',
            'period_from' => 'nullable|date', 'period_to' => 'nullable|date', 'amount_claimed' => 'required|numeric|min:0.01',
            'amount_certified' => 'nullable|numeric|min:0', 'remarks' => 'nullable|max:500']);
    }
    protected function compute(array &$d, float $retPct): void {
        $cert = (float) ($d['amount_certified'] ?? $d['amount_claimed']);
        $d['amount_certified'] = $cert;
        $d['retention_deducted'] = round($cert * $retPct / 100, 2);
        $d['tax_withheld'] = GhanaTaxService::withholding($cert, 'services');
        $d['net_payable'] = round($cert - $d['retention_deducted'] - $d['tax_withheld'], 2);
    }
    protected function formData(M\SubcontractorClaim $c): array {
        return ['record' => $c, 'isNew' => !$c->exists, 'cfg' => CrudRegistry::get('subcontractor-claims'), 'key' => 'subcontractor-claims',
            'docNo' => $c->exists ? $c->claim_no : SequenceService::peek('subcontractor_claim'),
            'subs' => M\Subcontract::with('project')->orderByDesc('id')->get()];
    }
}
