<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Purchase;
use App\Models\Supplier;
use Carbon\Carbon;
use Illuminate\Http\Request;

/**
 * Accounts Payable — supplier payable ledger.
 */
class ApController extends Controller
{
    /**
     * List suppliers with outstanding payable balances, with aging info.
     */
    public function index(Request $request)
    {
        $this->authorize('view-reports');

        $search  = $request->input('search');
        $bucket  = $request->input('bucket');   // 0_30 | 31_60 | 61_90 | 90_plus
        $perPage = min((int) $request->input('per_page', 20), 100);
        $today   = Carbon::today();

        $query = Supplier::query()
            ->whereHas('purchases', function ($q) {
                $q->where('amount_due', '>', 0)
                  ->whereNotIn('status', ['cancelled']);
            })
            ->withSum(['purchases as total_outstanding' => function ($q) {
                $q->where('amount_due', '>', 0)
                  ->whereNotIn('status', ['cancelled']);
            }], 'amount_due')
            ->with(['purchases' => function ($q) {
                $q->where('amount_due', '>', 0)
                  ->whereNotIn('status', ['cancelled'])
                  ->select(
                      'id', 'supplier_id', 'purchase_number', 'purchase_date',
                      'total', 'amount_paid', 'amount_due', 'payment_status', 'status'
                  )
                  ->orderBy('purchase_date');
            }]);

        if ($search) {
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                  ->orWhere('phone', 'like', "%{$search}%")
                  ->orWhere('email', 'like', "%{$search}%")
                  ->orWhere('company', 'like', "%{$search}%");
            });
        }

        $paginated = $query->orderByDesc('total_outstanding')->paginate($perPage);

        // Decorate with aging buckets
        $paginated->getCollection()->transform(function ($supplier) use ($today) {
            $buckets    = ['0_30' => 0, '31_60' => 0, '61_90' => 0, '90_plus' => 0];
            $maxDays    = 0;
            $oldestDate = null;

            foreach ($supplier->purchases as $purchase) {
                $days = (int) $today->diffInDays(Carbon::parse($purchase->purchase_date));
                if ($days > $maxDays) $maxDays = $days;
                if (!$oldestDate || Carbon::parse($purchase->purchase_date)->lt(Carbon::parse($oldestDate))) {
                    $oldestDate = $purchase->purchase_date;
                }
                $purchase->days_outstanding = $days;
                $purchase->aging_bucket     = $this->resolveBucket($days);
                $buckets[$this->resolveBucket($days)] += (float) $purchase->amount_due;
            }

            $supplier->aging_buckets          = $buckets;
            $supplier->oldest_purchase_date   = $oldestDate;
            $supplier->max_days_outstanding   = $maxDays;

            return $supplier;
        });

        // Filter by aging bucket after decoration
        if ($bucket && in_array($bucket, ['0_30', '31_60', '61_90', '90_plus'])) {
            $filtered = $paginated->getCollection()
                ->filter(fn($s) => ($s->aging_buckets[$bucket] ?? 0) > 0)
                ->values();
            $paginated->setCollection($filtered);
        }

        return response()->json($paginated);
    }

    /**
     * Global AP summary: total payable and aging buckets.
     */
    public function summary(Request $request)
    {
        $this->authorize('view-reports');

        $today     = Carbon::today();
        $purchases = Purchase::where('amount_due', '>', 0)
            ->whereNotIn('status', ['cancelled'])
            ->select('supplier_id', 'amount_due', 'purchase_date')
            ->get();

        $buckets         = ['0_30' => 0, '31_60' => 0, '61_90' => 0, '90_plus' => 0];
        $totalOutstanding = 0.0;

        foreach ($purchases as $purchase) {
            $totalOutstanding += (float) $purchase->amount_due;
            $days              = (int) $today->diffInDays(Carbon::parse($purchase->purchase_date));
            $buckets[$this->resolveBucket($days)] += (float) $purchase->amount_due;
        }

        $creditorCount = $purchases->whereNotNull('supplier_id')
            ->pluck('supplier_id')
            ->unique()
            ->count();

        return response()->json([
            'total_outstanding' => $totalOutstanding,
            'creditor_count'    => $creditorCount,
            'buckets'           => $buckets,
        ]);
    }

    // -------------------------------------------------------------------------
    // Helpers
    // -------------------------------------------------------------------------

    private function resolveBucket(int $days): string
    {
        if ($days <= 30)  return '0_30';
        if ($days <= 60)  return '31_60';
        if ($days <= 90)  return '61_90';
        return '90_plus';
    }
}
