<?php

namespace App\Http\Controllers\Dashboard\Admin;

use App\Models\User;
use App\Models\Transaction;
use App\Models\Notification;
use Illuminate\Http\Request;
use App\Enum\TransactionType;
use App\Enum\TransactionStatus;
use App\Enum\TransactionDirection;
use App\Enum\TransactionMethod;
use Illuminate\Support\Facades\DB;
use App\Mail\TransactionSuccessful;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Mail;
use App\Http\Requests\StoreTransactionRequest;

class UserTransactionController extends Controller
{
    public function index(string $uuid)
    {
        $breadcrumbs = [
            ['label' => config('app.name'), 'url' => '/'],
            ['label' => 'Dashboard', 'url' => route('admin.dashboard')],
            ['label' => 'Users', 'url' => route('admin.user.index')],
            ['label' => 'User Details', 'url' => route('admin.user.show', $uuid)],
            ['label' => 'Transactions', 'active' => true]
        ];

        $user = User::where('uuid', $uuid)->firstOrFail();
        $transactions = $user->transaction()->with(['user'])->latest()->get();

        $data = [
            'title' => 'Transactions',
            'user' => $user,
            'breadcrumbs' => $breadcrumbs,
            'transactions' => $transactions,
            'transactionTypes' => TransactionType::cases(),
            'transactionDirections' => TransactionDirection::cases(),
        ];

        return view('dashboard.admin.user.transaction.index', $data);
    }

    public function store(StoreTransactionRequest $request, $uuid)
    {
        $validated = $request->validated();

        try {
            DB::beginTransaction();

            $user = User::where('uuid', $uuid)->firstOrFail();

            switch ($request->direction) {
                case 'debit':
                    if ($user->balance < $request->amount) {
                        DB::rollBack();
                        return redirect()->back()->with('error', 'Insufficient balance!');
                    }

                    $user->balance = $user->balance - $request->amount;
                    $user->save();
                    break;
                case 'credit':
                    $user->balance = $user->balance + $request->amount;
                    $user->save();
                    break;
            }

            // Transaction
            $description = match ($request->direction) {
                'credit' => "Credit transaction of " . currency($user->currency) . formatAmount($request->amount) . " successfully processed.",
                'debit' => "Debit transaction of " . currency($user->currency) . formatAmount($request->amount) . " successfully processed.",
            };

            $transaction = Transaction::create([
                'user_id' => $user->id,
                'type' => $request->type,
                'direction' => $request->direction,
                'description' => $request->description ?? $description,
                'amount' => $request->amount,
                'method' => TransactionMethod::BANK,
                'transaction_at' => $request->transaction_at,
                'reference_id' => generateReferenceId(),
                'status' => TransactionStatus::COMPLETED
            ]);

            // Notification
            $message = match ($request->direction) {
                'credit' => "Your account has been credited with " . currency($user->currency) . formatAmount($request->amount) .
                    ". Your new balance is " . currency($user->currency) . formatAmount($user->balance) . ".",

                'debit' => "An amount of " . currency($user->currency) . formatAmount($request->amount) .
                    " has been debited from your account. Your new balance is " . currency($user->currency) . formatAmount($user->balance) . ".",
            };

            Notification::create([
                'user_id' => $user->id,
                'title' => ucwords($request->type) . ' Transaction',
                'description' => $message,
            ]);

            if ($request->notification == 'email') {
                Mail::to($user->email)->queue(new TransactionSuccessful($user, $transaction));
            }

            DB::commit();

            return redirect()->route('admin.user.transaction.index', [$user->uuid])->with('success', 'Transaction created successfully!');
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error($e->getMessage());
            return redirect()->back()->with('error', config('app.messages.error'));
        }
    }

    public function show(string $uuid, string $transactionUUID)
    {
        $breadcrumbs = [
            ['label' => config('app.name'), 'url' => '/'],
            ['label' => 'Dashboard', 'url' => route('admin.dashboard')],
            ['label' => 'Users', 'url' => route('admin.user.index')],
            ['label' => 'User Details', 'url' => route('admin.user.show', $uuid)],
            ['label' => 'Transactions', 'url' => route('admin.user.transaction.index', $uuid)],
            ['label' => 'Transaction Details', 'active' => true]
        ];

        $user = User::where('uuid', $uuid)->firstOrFail();
        $transaction = $user->transaction()->where('uuid', $transactionUUID)->firstOrFail();

        $data = [
            'title' => 'Transaction Details',
            'user' => $user,
            'breadcrumbs' => $breadcrumbs,
            'transaction' => $transaction
        ];

        return view('dashboard.admin.user.transaction.show', $data);
    }

    public function delete($uuid, $transactionUUID)
    {
        try {
            DB::beginTransaction();

            $user = User::where('uuid', $uuid)->firstOrFail();
            $transaction = $user->transaction()->where('uuid', $transactionUUID)->firstOrFail();

            $transaction->delete();

            DB::commit();

            return redirect()->route('admin.user.transaction.index', [$user->uuid])->with('success', 'Transaction deleted successfully!');
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error($e->getMessage());
            return redirect()->back()->with('error', config('app.messages.error'));
        }
    }
}
