<?php

namespace App\Http\Controllers;

use App\Models\MatchModel;
use App\Models\Ticket;
use App\Models\User;
use App\Traits\AuditLogTrait;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use SimpleSoftwareIO\QrCode\Facades\QrCode;

class TicketController extends Controller
{
    use AuditLogTrait;

    public function create()
    {
        $matches = MatchModel::with('seats')->get();
        return view('tickets.create-ticket', compact('matches'));
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'match_id' => 'required|exists:matches,match_id',
            'seat_id' => 'required|exists:seats,id',
            'category' => 'required|in:vvip,vip,1st_class',
            'purchase_channel' => 'required|in:online,ticket_center',
            'status' => 'required|in:valid,used,cancelled',
            'amount' => 'required|numeric|min:0',
        ]);

        // Use a transaction to prevent race conditions
        return DB::transaction(function () use ($validated, $request) {
            // Fetch the match with seats
            $match = MatchModel::with('seats')->findOrFail($validated['match_id']);

            // Fetch the specific match-seat pivot
            $matchSeat = $match->seats->where('id', $validated['seat_id'])->first();

            if (!$matchSeat) {
                throw ValidationException::withMessages([
                    'seat_id' => 'Selected block is not available for this match.',
                ]);
            }

            // Check if category matches the block's type
            $expectedCategory = strtolower(str_replace(' ', '_', $matchSeat->type));
            if ($validated['category'] !== $expectedCategory) {
                throw ValidationException::withMessages([
                    'category' => 'Selected category does not match the block\'s seat type.',
                ]);
            }

            // Count existing tickets for this specific block in the match
            $soldInBlock = Ticket::where('match_id', $validated['match_id'])
                ->where('seat_id', $validated['seat_id'])
                ->count();

            // Check if adding a new ticket would exceed the block's limit
            if ($soldInBlock >= $matchSeat->pivot->available_tickets) {
                throw ValidationException::withMessages([
                    'seat_id' => 'No more tickets available for this block.',
                ]);
            }

            $ticketNumber = 'TICKET-' . Str::random(8);

            // Use SVG format instead of PNG (doesn't require imagick)
            $qrCodeSvg = QrCode::size(300)->generate(url('/tickets/verify/' . $ticketNumber));

            $ticket = Ticket::create([
                'match_id' => $validated['match_id'],
                'category' => $validated['category'],
                'user_id' => auth()->id() ?? 1,
                'ticket_number' => $ticketNumber,
                'qr_code' => $qrCodeSvg,
                'purchase_channel' => $validated['purchase_channel'],
                'status' => $validated['status'],
                'seat_id' => $validated['seat_id'],
            ]);

            // Decrement available tickets for the block
            $match->seats()->updateExistingPivot($validated['seat_id'], [
                'available_tickets' => DB::raw('available_tickets - 1')
            ]);

            // Save transaction
            $transaction = \App\Models\TransactionModel::create([
                'ticket_id' => $ticket->ticket_id,
                'user_id' => $ticket->user_id,
                'amount' => $validated['amount'],
                'payment_method' => 'cash', // Default, or set from request if needed
            ]);

            // Save revenue shares for this transaction
            \App\Models\Revenue::createFromTransaction($transaction->txn_id, $validated['amount']);

            $ticket->load('match', 'seat');

            $this->logCreate($ticket, "Created new ticket: {$ticket->ticket_number} by user: " . auth()->user()->name);

            return redirect()->route('tickets.create')->with('ticket', $ticket);
        });
    }

    // process the ticket created by the fan through stripe

    /**
     * Process fan ticket purchase with payment
     */
    public function fans_store(Request $request)
    {
        $rate = 0.000218;
        $amount = $request->amount;
        $amount = $amount * $rate;
        $validated = $request->validate([
            'match_id' => 'required|exists:matches,match_id',
            'seat_id' => 'required|exists:seats,id',
            'category' => 'required|in:vvip,vip,1st_class',
            'amount' => $amount,
            'payment_method' => 'required|in:stripe,paypal',
        ]);

        // Store ticket data in session for after payment
        session([
            'pending_ticket' => [
                'match_id' => $validated['match_id'],
                'seat_id' => $validated['seat_id'],
                'category' => $validated['category'],
                'amount' => $amount,
                'payment_method' => $validated['payment_method'],
                'user_id' => auth()->id(),
            ]
        ]);

        // Redirect to appropriate payment gateway
        if ($validated['payment_method'] === 'stripe') {
            return $this->initiateStripePayment($validated);
        } else {
            return $this->initiatePayPalPayment($validated);
        }
    }

    /**
     * Initiate Stripe payment
     */
    private function initiateStripePayment($data)
    {
        try {
            \Stripe\Stripe::setApiKey(config('services.stripe.secret'));

            $match = MatchModel::findOrFail($data['match_id']);
            
            $session = \Stripe\Checkout\Session::create([
                'payment_method_types' => ['card'],
                'line_items' => [[
                    'price_data' => [
                        'currency' => 'usd', // Change to your currency
                        'product_data' => [
                            'name' => "Ticket: {$match->home_team} vs {$match->away_team}",
                            'description' => "Category: {$data['category']}",
                        ],
                        'unit_amount' => $data['amount'] * 100, // Stripe uses cents
                    ],
                    'quantity' => 1,
                ]],
                'mode' => 'payment',
                'success_url' => route('tickets.payment.success') . '?session_id={CHECKOUT_SESSION_ID}',
                'cancel_url' => route('tickets.payment.cancel'),
                'metadata' => [
                    'match_id' => $data['match_id'],
                    'seat_id' => $data['seat_id'],
                    'category' => $data['category'],
                ],
            ]);

            return redirect($session->url);
        } catch (\Exception $e) {
            return back()->withErrors(['payment' => 'Payment initialization failed: ' . $e->getMessage()]);
        }
    }

    /**
     * Initiate PayPal payment
     */
    private function initiatePayPalPayment($data)
    {
        // Implement PayPal payment logic
        // Integrate PayPal SDK
        return back()->withErrors(['payment' => 'PayPal integration coming soon']);
    }

    /**
     * Handle successful payment
     */
    public function paymentSuccess(Request $request)
    {
        try {
            // Retrieve pending ticket data from session
            $pendingTicket = session('pending_ticket');
            
            if (!$pendingTicket) {
                return redirect()->route('fans.fancreateticket')
                    ->withErrors(['error' => 'No pending ticket found']);
            }

            // Verify payment with Stripe
            if ($request->has('session_id')) {
                \Stripe\Stripe::setApiKey(config('services.stripe.secret'));
                $session = \Stripe\Checkout\Session::retrieve($request->session_id);
                
                if ($session->payment_status !== 'paid') {
                    throw new \Exception('Payment not completed');
                }
            }

            // Create the ticket using a transaction
            return DB::transaction(function () use ($pendingTicket) {
                $match = MatchModel::with('seats')->findOrFail($pendingTicket['match_id']);
                $matchSeat = $match->seats->where('id', $pendingTicket['seat_id'])->first();

                if (!$matchSeat) {
                    throw ValidationException::withMessages([
                        'seat_id' => 'Selected block is not available for this match.',
                    ]);
                }

                // Check category matches
                $expectedCategory = strtolower(str_replace(' ', '_', $matchSeat->type));
                if ($pendingTicket['category'] !== $expectedCategory) {
                    throw ValidationException::withMessages([
                        'category' => 'Selected category does not match the block\'s seat type.',
                    ]);
                }

                // Check availability
                $soldInBlock = Ticket::where('match_id', $pendingTicket['match_id'])
                    ->where('seat_id', $pendingTicket['seat_id'])
                    ->count();

                if ($soldInBlock >= $matchSeat->pivot->available_tickets) {
                    throw ValidationException::withMessages([
                        'seat_id' => 'No more tickets available for this block.',
                    ]);
                }

                $ticketNumber = 'TICKET-' . Str::random(8);
                $qrCodeSvg = QrCode::size(300)->generate(url('/tickets/verify/' . $ticketNumber));

                $ticket = Ticket::create([
                    'match_id' => $pendingTicket['match_id'],
                    'category' => $pendingTicket['category'],
                    'user_id' => $pendingTicket['user_id'],
                    'ticket_number' => $ticketNumber,
                    'qr_code' => $qrCodeSvg,
                    'purchase_channel' => 'online',
                    'status' => 'valid',
                    'seat_id' => $pendingTicket['seat_id'],
                ]);

                // Decrement available tickets
                $match->seats()->updateExistingPivot($pendingTicket['seat_id'], [
                    'available_tickets' => DB::raw('available_tickets - 1')
                ]);

                // Save transaction
                $transaction = \App\Models\TransactionModel::create([
                    'ticket_id' => $ticket->ticket_id,
                    'user_id' => $ticket->user_id,
                    'amount' => $pendingTicket['amount'],
                    'payment_method' => 'card',
                ]);

                // Save revenue shares
                \App\Models\Revenue::createFromTransaction($transaction->txn_id, $pendingTicket['amount']);

                $ticket->load('match', 'seat');

                $this->logCreate($ticket, "Fan created ticket online: {$ticket->ticket_number}");

                // Clear session data
                session()->forget('pending_ticket');

                return redirect()->route('fans.fancreateticket')->with('ticket', $ticket);
            });

        } catch (\Exception $e) {
            return redirect()->route('fans.fancreateticket')
                ->withErrors(['error' => 'Ticket creation failed: ' . $e->getMessage()]);
        }
    }

    /**
     * Handle cancelled payment
     */
    public function paymentCancel()
    {
        session()->forget('pending_ticket');
        return redirect()->route('fans.fancreateticket')
            ->with('error', 'Payment was cancelled. Please try again.');
    }

    public function verify($ticketNumber)
    {
        $ticket = Ticket::where('ticket_number', $ticketNumber)->first();

        if (!$ticket) {
            return view('tickets.verification-result', ['status' => 'unverified', 'message' => 'Ticket not found.']);
        }

        if ($ticket->status === 'valid') {
            $ticket->status = 'used';
            $ticket->save();
            $this->logUpdate($ticket, "Ticket {$ticket->ticket_number} marked as used upon verification.");
            return view('tickets.verification-result', ['status' => 'verified', 'message' => 'Ticket Verified Successfully!']);
        } else {
            return view('tickets.verification-result', ['status' => 'unverified', 'message' => 'Ticket has already been used or is cancelled.']);
        }
    }
}
