<?php

namespace App\Http\Controllers\Api\Finance;

use App\Http\Controllers\Controller;
use App\Http\Requests\Finance\EventChargeLifecycleRequest;
use App\Models\EventCharge;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

class EventChargeController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        $q = EventCharge::query();
        foreach (['parent_id','student_id','event_id','school_year','semester'] as $field) {
            if ($request->filled($field)) $q->where($field, $request->query($field));
        }
        if ($request->filled('status')) {
            $status = $request->query('status');
            if (Schema::hasColumn('event_charges', 'status')) $q->where('status', $status);
            elseif ($status === 'paid') $q->where('event_paid', 1);
            elseif ($status === 'pending') $q->where(function ($qq) { $qq->whereNull('event_paid')->orWhere('event_paid', 0); });
        }
        return response()->json(['ok' => true, 'event_charges' => $q->orderByDesc('id')->paginate((int) $request->query('per_page', 25))]);
    }

    public function store(EventChargeLifecycleRequest $request): JsonResponse
    {
        $data = $this->normalizePayload($request->validated());
        $data['created_by'] = optional($request->user())->id;
        if (Schema::hasColumn('event_charges', 'status')) $data['status'] = $data['status'] ?? 'draft';
        $charge = EventCharge::query()->create($data);
        return response()->json(['ok' => true, 'event_charge' => $charge], 201);
    }

    public function show(int $eventCharge): JsonResponse
    {
        return response()->json(['ok' => true, 'event_charge' => EventCharge::query()->findOrFail($eventCharge)]);
    }

    public function update(EventChargeLifecycleRequest $request, int $eventCharge): JsonResponse
    {
        $charge = EventCharge::query()->findOrFail($eventCharge);
        $charge->fill($this->normalizePayload($request->validated()))->save();
        return response()->json(['ok' => true, 'event_charge' => $charge->fresh()]);
    }

    public function destroy(int $eventCharge): JsonResponse
    {
        return $this->void($eventCharge);
    }

    public function approve(int $eventCharge): JsonResponse
    {
        $charge = EventCharge::query()->findOrFail($eventCharge);
        if (Schema::hasColumn('event_charges', 'status')) $charge->status = 'approved';
        if (Schema::hasColumn('event_charges', 'charged')) $charge->charged = 1;
        $charge->save();
        return response()->json(['ok' => true, 'event_charge' => $charge->fresh()]);
    }

    public function void(int $eventCharge): JsonResponse
    {
        $charge = EventCharge::query()->findOrFail($eventCharge);
        if (Schema::hasColumn('event_charges', 'status')) $charge->status = 'voided';
        if (Schema::hasColumn('event_charges', 'charged')) $charge->charged = 0;
        $charge->save();
        return response()->json(['ok' => true, 'event_charge' => $charge->fresh()]);
    }

    public function attachToInvoice(Request $request, int $eventCharge): JsonResponse
    {
        $request->validate(['invoice_id' => ['required','integer']]);
        $charge = EventCharge::query()->findOrFail($eventCharge);
        $invoiceId = (int) $request->input('invoice_id');
        abort_if(!DB::table('invoices')->where('id', $invoiceId)->exists(), 404, 'Invoice not found.');
        if (Schema::hasColumn('event_charges', 'invoice_id')) $charge->invoice_id = $invoiceId;
        if (Schema::hasColumn('event_charges', 'status')) $charge->status = 'invoiced';
        if (Schema::hasColumn('event_charges', 'charged')) $charge->charged = 1;
        $charge->save();
        return response()->json(['ok' => true, 'event_charge' => $charge->fresh(), 'warning' => Schema::hasColumn('event_charges','invoice_id') ? null : 'invoice_id column does not exist; charge marked as charged only.']);
    }

    private function normalizePayload(array $data): array
    {
        if (isset($data['title']) && !isset($data['event_name'])) $data['event_name'] = $data['title'];
        unset($data['title'], $data['invoice_id']);
        return array_filter($data, fn($v) => $v !== null);
    }
}
