<?php

namespace App\Http\Controllers\User;

use App\Http\Controllers\Controller;
use App\Models\AtmCard;
use App\Models\Transaction;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class AtmCardController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | ATM Card Controller
    
    |--------------------------------------------------------------------------
    | Handles the full lifecycle of a user's virtual/physical ATM card:
    |   index    → list all cards
    |   create   → show application form
    |   store    → submit card application
    |   show     → single card detail
    |   freeze   → user freezes an active card
    |   unfreeze → user unfreezes a frozen card
    |   cancel   → user permanently cancels a card
    |   setPin   → user sets or changes card PIN
    |--------------------------------------------------------------------------
    */

    /**
     * List all cards for the authenticated user.
     */
    public function index(Request $request)
    {
        $user = auth()->user();

        $cards = AtmCard::where('user_id', $user->id)
            ->when($request->search,  fn($q) => $q->search($request->search))
            ->when($request->network, fn($q) => $q->where('card_network', $request->network))
            ->when($request->type,    fn($q) => $q->where('card_type', $request->type))
            ->when($request->status !== null, fn($q) => $q->where('status', $request->status))
            ->latest()
            ->paginate(getPaginate());

        $pageTitle    = 'My Cards';
        $emptyMessage = 'No cards found.';

        return view($this->activeTemplate . 'user.atm_card.index', compact(
            'cards',
            'pageTitle',
            'emptyMessage'
        ));
    }

    /**
     * Show the card application form.
     */
    public function create()
    {
        $user    = auth()->user();
        $general = gs();

        // Check max card limit per user (configurable)
        $cardLimit  = $general->max_cards_per_user ?? 3;
        $activeCount = AtmCard::where('user_id', $user->id)
            ->whereIn('status', [AtmCard::STATUS_PENDING, AtmCard::STATUS_ACTIVE, AtmCard::STATUS_FROZEN])
            ->count();

        if ($activeCount >= $cardLimit) {
            $notify[] = ['error', "You have reached the maximum limit of {$cardLimit} active cards."];
            return redirect()->route('user.cards.index')->withNotify($notify);
        }

        $pageTitle = 'Apply for a Card';

        return view($this->activeTemplate . 'user.atm_card.create', compact(
            'general',
            'pageTitle'
        ));
    }

    /**
     * Submit a new card application.
     */
    public function store(Request $request)
    {
        $request->validate([
            'card_network'    => 'required|in:visa,mastercard',
            'card_type'       => 'required|in:virtual,physical',
            'billing_address' => 'nullable|string|max:255',
            'billing_city'    => 'nullable|string|max:100',
            'billing_state'   => 'nullable|string|max:100',
            'billing_zip'     => 'nullable|string|max:20',
            'billing_country' => 'nullable|string|max:100',
        ]);

        $user    = auth()->user();
        $general = gs();

        // Card issuance fee (extend as needed)
        $issuanceFee = $general->card_issuance_fee ?? 0;

        if ($issuanceFee > 0 && $user->balance < $issuanceFee) {
            $notify[] = ['error', 'Insufficient balance to cover the card issuance fee.'];
            return back()->withNotify($notify);
        }

        DB::transaction(function () use ($request, $user, $general, $issuanceFee) {

            // Generate card credentials
            $network    = $request->card_network;
            $rawNumber  = AtmCard::generateCardNumber($network);
            $rawCvv     = AtmCard::generateCvv();
            $expiryDate = now()->addYears(4);

            // Create card record
            $card = AtmCard::create([
                'user_id'         => $user->id,
                'card_number'     => encrypt($rawNumber),
                'masked_number'   => AtmCard::maskCardNumber($rawNumber),
                'holder_name'     => $user->fullname,
                'expiry_month'    => $expiryDate->format('m'),
                'expiry_year'     => $expiryDate->format('Y'),
                'cvv'             => AtmCard::hashSecret($rawCvv),
                'card_network'    => $network,
                'card_type'       => $request->card_type,
                'currency'        => $general->cur_text,
                'billing_address' => $request->billing_address,
                'billing_city'    => $request->billing_city,
                'billing_state'   => $request->billing_state,
                'billing_zip'     => $request->billing_zip,
                'billing_country' => $request->billing_country ?? $user->address?->country,
                'status'          => AtmCard::STATUS_PENDING,
            ]);

            // Debit issuance fee if applicable
            if ($issuanceFee > 0) {
                $user->balance -= $issuanceFee;
                $user->save();

                $trx                       = getTrx();
                $transaction               = new Transaction();
                $transaction->user_id      = $user->id;
                $transaction->amount       = $issuanceFee;
                $transaction->post_balance = $user->balance;
                $transaction->charge       = 0;
                $transaction->trx_type     = '-';
                $transaction->details      = 'Card Issuance Fee — ' . $card->network_label . ' (' . $card->masked_number . ')';
                $transaction->trx          = $trx;
                $transaction->remark       = 'card_issuance_fee';
                $transaction->save();
            }

            // Virtual cards can be auto-activated
            if ($request->card_type === AtmCard::TYPE_VIRTUAL) {
                $card->activate();
            }
        });

        $notify[] = ['success', 'Card application submitted successfully.'];
        return redirect()->route('user.cards.index')->withNotify($notify);
    }

    /**
     * Show a single card detail.
     */
    public function show(int $id)
    {
        $user = auth()->user();

        $card    = AtmCard::where('user_id', $user->id)->findOrFail($id);
        $general = gs();

        $pageTitle = 'Card Detail';

        return view($this->activeTemplate . 'user.atm_card.show', compact(
            'card',
            'general',
            'pageTitle'
        ));
    }

    /**
     * Freeze an active card.
     */
    public function freeze(int $id)
    {
        $user = auth()->user();

        $card = AtmCard::where('user_id', $user->id)
            ->where('status', AtmCard::STATUS_ACTIVE)
            ->findOrFail($id);

        $card->freeze();

        $notify[] = ['success', 'Your card has been frozen. You can unfreeze it at any time.'];
        return back()->withNotify($notify);
    }

    /**
     * Unfreeze a frozen card.
     */
    public function unfreeze(int $id)
    {
        $user = auth()->user();

        $card = AtmCard::where('user_id', $user->id)
            ->where('status', AtmCard::STATUS_FROZEN)
            ->findOrFail($id);

        $card->unfreeze();

        $notify[] = ['success', 'Your card has been unfrozen and is now active.'];
        return back()->withNotify($notify);
    }

    /**
     * Permanently cancel a card.
     */
    public function cancel(Request $request, int $id)
    {
        $user = auth()->user();

        $card = AtmCard::where('user_id', $user->id)
            ->whereNotIn('status', [AtmCard::STATUS_CANCELLED, AtmCard::STATUS_BLOCKED])
            ->findOrFail($id);

        $card->cancel();

        $notify[] = ['success', 'Your card has been permanently cancelled.'];
        return redirect()->route('user.cards.index')->withNotify($notify);
    }

    /**
     * Set or update the card PIN.
     */
    public function setPin(Request $request, int $id)
    {
        $request->validate([
            'pin'              => 'required|digits:4|confirmed',
            'pin_confirmation' => 'required|digits:4',
        ]);

        $user = auth()->user();

        $card = AtmCard::where('user_id', $user->id)
            ->whereIn('status', [AtmCard::STATUS_ACTIVE, AtmCard::STATUS_PENDING])
            ->findOrFail($id);

        $card->pin = AtmCard::hashSecret($request->pin);
        $card->save();

        $notify[] = ['success', 'Card PIN has been set successfully.'];
        return back()->withNotify($notify);
    }
}
