<?php

namespace App\Http\Controllers;

use App\Models\Transaksi;
use App\Models\Tiket;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class TransaksiController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | ADMIN - Semua Transaksi
    |--------------------------------------------------------------------------
    */

    public function index(\Illuminate\Http\Request $request)
    {
        $perPage = (int) $request->query('perpage', 10);

        $query = Transaksi::with(['user', 'tiket.event']);

        if ($search = $request->query('search')) {
            $query->where(function($q) use ($search) {
                $q->where('nama_pembeli', 'like', "%{$search}%")
                  ->orWhereHas('user', function($qu) use ($search) {
                      $qu->where('name', 'like', "%{$search}%")->orWhere('email', 'like', "%{$search}%");
                  })
                  ->orWhereHas('tiket.event', function($qe) use ($search) {
                      $qe->where('nama_event', 'like', "%{$search}%");
                  });
            });
        }

        if ($status = $request->query('status')) {
            $query->where('status', $status);
        }

        if ($date = $request->query('date_filter')) {
            if ($date === 'today') {
                $query->whereDate('created_at', now()->toDateString());
            } elseif ($date === 'this_week') {
                $query->whereBetween('created_at', [now()->startOfWeek(), now()->endOfWeek()]);
            } elseif ($date === 'this_month') {
                $query->whereYear('created_at', now()->year)->whereMonth('created_at', now()->month);
            } elseif ($date === 'custom') {
                $from = $request->query('date_from');
                $to = $request->query('date_to');
                if ($from) $query->whereDate('created_at', '>=', $from);
                if ($to) $query->whereDate('created_at', '<=', $to);
            }
        }

        $query->orderBy('created_at', 'desc');

        $transaksis = $query->paginate($perPage)->appends($request->except('page'));

        return view('transaksi.index', compact('transaksis'));
    }

    /*
    |--------------------------------------------------------------------------
    | ADMIN - Form Tambah
    |--------------------------------------------------------------------------
    */

    public function create()
    {
        $tikets = Tiket::with('event')->get();

        return view('transaksi.create', compact('tikets'));
    }

    /*
    |--------------------------------------------------------------------------
    | ADMIN - Simpan
    |--------------------------------------------------------------------------
    */

    public function store(Request $request)
    {
        $request->validate([
            'tiket_id' => 'required|exists:tikets,id',
            'nama_pembeli' => 'required',
            'jumlah' => 'required|integer|min:1',
            'metode_pembayaran' => 'required|string|max:50',
            'status' => 'required|in:Pending,Confirmed,Rejected',
        ]);

        DB::beginTransaction();

        try {
            $tiket = Tiket::findOrFail($request->tiket_id);

            if ($tiket->stok < $request->jumlah) {
                return back()->with('error', 'Stok tiket tidak mencukupi.');
            }

            $total = $tiket->harga * $request->jumlah;

            $transaksi = Transaksi::create([
                'user_id' => auth()->id(),
                'tiket_id' => $tiket->id,
                'nama_pembeli' => $request->nama_pembeli,
                'jumlah' => $request->jumlah,
                'total_harga' => $total,
                'metode_pembayaran' => $request->metode_pembayaran,
                'status' => $request->status,
            ]);

            $tiket->decrement('stok', $request->jumlah);

            DB::commit();

            return redirect()
                ->route('transaksi.index')
                ->with('success', 'Transaksi berhasil.');
        } catch (\Throwable $e) {
            DB::rollBack();

            return back()->with('error', $e->getMessage());
        }
    }

    /*
    |--------------------------------------------------------------------------
    | ADMIN - Detail
    |--------------------------------------------------------------------------
    */

    public function show($id)
    {
        $transaksi = Transaksi::with([
            'user',
            'tiket.event',
        ])->findOrFail($id);

        return view('transaksi.show', compact('transaksi'));
    }

    /*
    |--------------------------------------------------------------------------
    | ADMIN - Edit
    |--------------------------------------------------------------------------
    */

    public function edit($id)
    {
        $transaksi = Transaksi::findOrFail($id);
        $tikets = Tiket::all();

        return view('transaksi.edit', compact('transaksi', 'tikets'));
    }

    /*
    |--------------------------------------------------------------------------
    | ADMIN - Update
    |--------------------------------------------------------------------------
    */

    public function update(Request $request, $id)
    {
        $request->validate([
            'tiket_id' => 'required|exists:tikets,id',
            'nama_pembeli' => 'required',
            'jumlah' => 'required|integer|min:1',
            'total_harga' => 'required|numeric',
            'metode_pembayaran' => 'required|string|max:50',
            'status' => 'required|in:Pending,Confirmed,Rejected',
        ]);

        $transaksi = Transaksi::findOrFail($id);
        $oldTiket = $transaksi->tiket;
        $oldJumlah = $transaksi->jumlah;
        $newTiket = Tiket::findOrFail($request->tiket_id);

        if ($oldTiket->id !== $newTiket->id) {
            $oldTiket->increment('stok', $oldJumlah);

            if ($newTiket->stok < $request->jumlah) {
                return back()->with('error', 'Stok tiket tidak mencukupi untuk tiket terpilih.');
            }

            $newTiket->decrement('stok', $request->jumlah);
        } else {
            $difference = $request->jumlah - $oldJumlah;

            if ($difference > 0 && $newTiket->stok < $difference) {
                return back()->with('error', 'Stok tiket tidak mencukupi.');
            }

            if ($difference > 0) {
                $newTiket->decrement('stok', $difference);
            } elseif ($difference < 0) {
                $newTiket->increment('stok', abs($difference));
            }
        }

        $transaksi->update([
            'tiket_id' => $request->tiket_id,
            'nama_pembeli' => $request->nama_pembeli,
            'jumlah' => $request->jumlah,
            'total_harga' => $request->total_harga,
            'metode_pembayaran' => $request->metode_pembayaran,
            'status' => $request->status,
        ]);

        return redirect()
            ->route('transaksi.index')
            ->with('success', 'Transaksi berhasil diperbarui.');
    }

    /*
    |--------------------------------------------------------------------------
    | ADMIN - Hapus
    |--------------------------------------------------------------------------
    */

    public function destroy($id)
    {
        $transaksi = Transaksi::findOrFail($id);

        if ($transaksi->tiket) {
            $transaksi->tiket->increment('stok', $transaksi->jumlah);
        }

        $transaksi->delete();

        return redirect()
            ->route('transaksi.index')
            ->with('success', 'Transaksi berhasil dihapus.');
    }

    /*
    |--------------------------------------------------------------------------
    | ADMIN - Konfirmasi
    |--------------------------------------------------------------------------
    */

    public function konfirmasi(Request $request, $id)
    {
        $request->validate([
            'status' => 'required|in:Pending,Confirmed,Rejected',
        ]);

        $transaksi = Transaksi::findOrFail($id);

        $transaksi->update([
            'status' => $request->status,
        ]);

        return back()->with('success', 'Status transaksi berhasil diperbarui.');
    }

    /*
    |--------------------------------------------------------------------------
    | USER - Beli Tiket
    |--------------------------------------------------------------------------
    */

    public function beli($id)
    {
        $tiket = Tiket::with('event')->findOrFail($id);
        return view('tiket.beli', compact('tiket'));
    }

    public function beliProcess($id, Request $request)
    {
        $tiket = Tiket::findOrFail($id);

        $request->validate([
            'nama_pembeli' => 'required',
            'jumlah' => 'required|integer|min:1',
            'metode_pembayaran' => 'required|string|max:50',
        ]);

        DB::beginTransaction();

        try {
            $jumlah = (int) $request->jumlah;

            if ($jumlah < 1) {
                return back()->with('error', 'Jumlah minimal pembelian adalah 1.');
            }

            // Refresh data stok agar tidak stale
            $tiket->refresh();

            if ((int) $tiket->stok <= 0) {
                return back()->with('error', 'Stok tiket habis.');
            }

            if ((int) $tiket->stok < $jumlah) {
                return back()->with('error', 'Stok tiket tidak cukup. Tersedia ' . $tiket->stok . ' tiket, tetapi Anda membeli ' . $jumlah . '.');
            }

            $total = $jumlah * $tiket->harga;

            $transaksi = Transaksi::create([
                'user_id' => auth()->id(),
                'tiket_id' => $tiket->id,
                'nama_pembeli' => $request->nama_pembeli,
                'jumlah' => $jumlah,
                'total_harga' => $total,
                'metode_pembayaran' => $request->metode_pembayaran,
                'status' => 'Pending',
            ]);

            $tiket->decrement('stok', $jumlah);

            DB::commit();

            return redirect()
                ->route('user.riwayat')
                ->with('success', 'Pembelian berhasil. Menunggu konfirmasi admin.');
        } catch (\Throwable $e) {
            DB::rollBack();

            return back()->with('error', $e->getMessage());
        }
    }
}