<?php

namespace App\Http\Controllers;

use App\Enums\RequestStatus;
use App\Enums\TransactionCategory;
use App\Enums\TransactionSource;
use App\Enums\TransactionStatus;
use App\Enums\TransactionType;
use App\Models\Account;
use App\Models\BillPayment;
use App\Models\Transaction;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

class BillPaymentController extends Controller
{
    public function index()
    {
        try {
            $accounts = auth()->user()->accounts;
            $recentPayments = BillPayment::whereIn('account_id', $accounts->pluck('id'))
                ->latest()
                ->take(10)
                ->get();

            return view('bill-payments.index', [
                'accounts' => $accounts,
                'recentPayments' => $recentPayments,
                'activePage' => 'bill-payments',
            ]);
        } catch (\Exception $e) {
            Log::error($e->getMessage());
            return back()->with('alert', 'An error occurred.');
        }
    }

    public function store(Request $request)
    {
        try {
            $request->validate([
                'from_account_id' => ['required', 'exists:accounts,id'],
                'biller_category' => ['required', 'string', 'max:100'],
                'biller_name' => ['required', 'string', 'max:255'],
                'biller_account_number' => ['required', 'string', 'max:100'],
                'amount' => ['required', 'numeric', 'min:0.01'],
                'description' => ['nullable', 'string', 'max:500'],
                'password' => ['required', 'string'],
            ]);

            if (!Hash::check($request->password, auth()->user()->password)) {
                return back()->withErrors(['password' => 'Invalid password.'])->withInput();
            }

            $account = Account::where('id', $request->from_account_id)
                ->where('user_id', auth()->id())
                ->firstOrFail();

            $fee = round($request->amount * 0.005, 2); // 0.5% processing fee
            $total = $request->amount + $fee;

            if ($account->balance < $total) {
                return back()->withErrors(['amount' => 'Insufficient balance. Total with fee: ' . $account->currency->symbol() . number_format($total, 2)])->withInput();
            }

            $ref = 'BP-' . strtoupper(Str::random(12));

            DB::transaction(function () use ($account, $request, $fee, $total, $ref) {
                $account->decrement('balance', $total);

                Transaction::create([
                    'account_id' => $account->id,
                    'type' => TransactionType::Debit,
                    'amount' => $total,
                    'balance_after' => $account->fresh()->balance,
                    'description' => 'Bill payment to ' . $request->biller_name,
                    'category' => TransactionCategory::Utilities,
                    'status' => TransactionStatus::Completed,
                    'source' => TransactionSource::BillPayment,
                    'reference' => $ref,
                ]);

                BillPayment::create([
                    'account_id' => $account->id,
                    'biller_name' => $request->biller_name,
                    'biller_category' => $request->biller_category,
                    'biller_account_number' => $request->biller_account_number,
                    'amount' => $request->amount,
                    'fee' => $fee,
                    'description' => $request->description,
                    'status' => RequestStatus::Approved,
                    'reference' => $ref,
                ]);
            });

            $transaction = Transaction::where('reference', $ref)->first();

            return redirect()->route('transactions.show', $transaction)->with('success', 'Bill payment completed successfully.');
        } catch (\Exception $e) {
            Log::error($e->getMessage());
            return back()->with('alert', 'An error occurred.');
        }
    }
}
