<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\AdminActivityLog;
use App\Models\PointsTransaction;
use App\Models\User;
use App\Models\Visit;
use App\Notifications\PointsCreditedNotification;
use App\Notifications\PointsDebitedNotification;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class PointsController extends Controller
{
    public function credit(Request $request, User $user)
    {
        $data = $request->validate([
            'spend_amount'           => ['required', 'numeric', 'min:0.01'],
            'visit_date'             => ['required', 'date', 'before_or_equal:today'],
            'notes'                  => ['nullable', 'string', 'max:500'],
            'admin_note'             => ['nullable', 'string', 'max:500'],
            'note_visible_to_member' => ['boolean'],
        ]);

        $points = (int) floor($data['spend_amount']);

        DB::transaction(function () use ($user, $data, $points, $request) {
            $visit = Visit::create([
                'user_id'       => $user->id,
                'visit_date'    => $data['visit_date'],
                'spend_amount'  => $data['spend_amount'],
                'points_awarded' => $points,
                'recorded_by'   => Auth::guard('admin')->id(),
                'notes'         => $data['notes'] ?? null,
            ]);

            $newBalance = $user->points_balance + $points;

            PointsTransaction::create([
                'user_id'                => $user->id,
                'type'                   => 'credit',
                'amount'                 => $points,
                'balance_after'          => $newBalance,
                'description'            => 'Visit recorded — $' . number_format($data['spend_amount'], 2) . ' spend',
                'visit_date'             => $data['visit_date'],
                'spend_amount'           => $data['spend_amount'],
                'visit_id'               => $visit->id,
                'admin_id'               => Auth::guard('admin')->id(),
                'admin_note'             => $data['admin_note'] ?? null,
                'note_visible_to_member' => $request->boolean('note_visible_to_member'),
            ]);

            $user->update(['points_balance' => $newBalance]);

            AdminActivityLog::create([
                'admin_id'    => Auth::guard('admin')->id(),
                'action'      => 'points.credit',
                'target_type' => User::class,
                'target_id'   => $user->id,
                'meta'        => ['points' => $points, 'spend' => $data['spend_amount'], 'visit_date' => $data['visit_date']],
                'ip_address'  => request()->ip(),
            ]);
        });

        // Send notification
        $user->notify(new PointsCreditedNotification(
            $points,
            $data['spend_amount'],
            $data['visit_date'],
            $user->fresh()->points_balance,
        ));

        return redirect()->route('admin.members.show', $user)
            ->with('success', "{$points} points added to {$user->full_name}'s account.");
    }

    public function debit(Request $request, User $user)
    {
        $data = $request->validate([
            'amount'                 => ['required', 'integer', 'min:1', 'max:' . $user->points_balance],
            'reason'                 => ['required', 'string', 'max:500'],
            'note_visible_to_member' => ['boolean'],
        ], [
            'amount.max' => 'Cannot deduct more points than the member currently has (' . $user->points_balance . ').',
        ]);

        DB::transaction(function () use ($user, $data) {
            $newBalance = $user->points_balance - $data['amount'];

            PointsTransaction::create([
                'user_id'                => $user->id,
                'type'                   => 'debit',
                'amount'                 => $data['amount'],
                'balance_after'          => $newBalance,
                'description'            => 'Points adjustment',
                'admin_id'               => Auth::guard('admin')->id(),
                'admin_note'             => $data['reason'],
                'note_visible_to_member' => request()->boolean('note_visible_to_member'),
            ]);

            $user->update(['points_balance' => $newBalance]);

            AdminActivityLog::create([
                'admin_id'    => Auth::guard('admin')->id(),
                'action'      => 'points.debit',
                'target_type' => User::class,
                'target_id'   => $user->id,
                'meta'        => ['points' => $data['amount'], 'reason' => $data['reason']],
                'ip_address'  => request()->ip(),
            ]);
        });

        // Send notification
        $user->notify(new PointsDebitedNotification(
            $data['amount'],
            $data['reason'],
            $user->fresh()->points_balance,
        ));

        return redirect()->route('admin.members.show', $user)
            ->with('success', "{$data['amount']} points deducted from {$user->full_name}'s account.");
    }

    public function history(User $user)
    {
        $transactions = $user->pointsTransactions()->with('admin', 'visit')->paginate(30);
        return view('admin.points.history', compact('user', 'transactions'));
    }

    public function ledger(Request $request)
    {
        $filter = $request->input('filter', 'all');
        $search = $request->input('search');

        $query = PointsTransaction::with(['user', 'admin'])
            ->when($filter === 'credit', fn ($q) => $q->where('type', 'credit'))
            ->when($filter === 'debit',  fn ($q) => $q->whereIn('type', ['debit', 'expiry']))
            ->when($search, fn ($q) => $q->whereHas('user', fn ($u) => $u
                ->where('first_name', 'like', "%{$search}%")
                ->orWhere('last_name',  'like', "%{$search}%")
                ->orWhere('email',      'like', "%{$search}%")
                ->orWhere('membership_number', 'like', "%{$search}%")
            ))
            ->latest();

        $transactions = $query->paginate(30)->withQueryString();

        $totalCredits = PointsTransaction::where('type', 'credit')->sum('amount');
        $totalDebits  = PointsTransaction::whereIn('type', ['debit', 'expiry'])->sum('amount');

        return view('admin.points.ledger', compact('transactions', 'filter', 'search', 'totalCredits', 'totalDebits'));
    }
}
