<?php

namespace App\Http\Controllers\Epelcon;

use App\Http\Controllers\Concerns\HandlesImageUploads;
use App\Http\Controllers\Controller;
use App\Models\ActivityLog;
use App\Models\Booking;
use App\Models\HotelService;
use App\Models\Payment;
use App\Models\ServiceBooking;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class ServiceController extends Controller
{
    use HandlesImageUploads;

    public const CATEGORIES = ['spa', 'swimming_pool', 'jacuzzi', 'pedicure', 'theater', 'banquet', 'gym', 'other'];

    public function index(Request $request)
    {
        $services = HotelService::when($request->filled('category'), fn ($q) => $q->where('category', $request->category))
            ->orderBy('name')
            ->get();

        $stats = [
            'services' => HotelService::count(),
            'today' => ServiceBooking::whereDate('scheduled_at', today())->where('status', '!=', 'cancelled')->count(),
            'revenue' => ServiceBooking::where('status', 'completed')->where('paid', true)
                ->whereBetween('scheduled_at', [now()->startOfMonth(), now()->endOfMonth()])
                ->sum('amount'),
        ];

        return view('epelcon.services.index', compact('services', 'stats'));
    }

    public function store(Request $request)
    {
        $data = $this->validateService($request);

        if ($image = $this->saveImage($request, 'image', 'services')) {
            $data['image'] = $image;
        }

        HotelService::create($data);
        ActivityLog::record('added service', 'services', $data['name']);

        return back()->with('success', "Service “{$data['name']}” added.");
    }

    public function update(Request $request, HotelService $service)
    {
        $data = $this->validateService($request);

        if ($image = $this->saveImage($request, 'image', 'services')) {
            $data['image'] = $image;
        }

        $service->update($data);

        return back()->with('success', 'Service updated.');
    }

    public function toggle(HotelService $service)
    {
        $service->update(['available' => ! $service->available]);

        return back()->with('success', "{$service->name} is now " . ($service->available ? 'available' : 'unavailable') . '.');
    }

    public function bookings(Request $request)
    {
        $bookings = ServiceBooking::with(['service', 'customer'])
            ->when($request->filled('status'), fn ($q) => $q->where('status', $request->status))
            ->orderByDesc('scheduled_at')
            ->paginate(15)->withQueryString();

        $services = HotelService::where('available', true)->orderBy('name')->get();
        $inHouse = Booking::with(['customer', 'room'])->where('status', 'checked_in')->get();

        return view('epelcon.services.bookings', compact('bookings', 'services', 'inHouse'));
    }

    public function storeBooking(Request $request)
    {
        $data = $request->validate([
            'hotel_service_id' => 'required|exists:hotel_services,id',
            'customer_name' => 'required|string|max:120',
            'phone' => 'nullable|string|max:40',
            'booking_id' => 'nullable|exists:bookings,id',
            'scheduled_at' => 'required|date',
            'guests' => 'nullable|integer|min:1',
            'amount' => 'nullable|numeric|min:0',
            'notes' => 'nullable|string',
        ]);

        $service = HotelService::findOrFail($data['hotel_service_id']);

        if (! empty($data['booking_id'])) {
            $data['customer_id'] = Booking::find($data['booking_id'])?->customer_id;
        }

        $data['code'] = 'SVC-' . strtoupper(Str::random(6));
        $data['guests'] = $data['guests'] ?? 1;
        $data['amount'] = $data['amount'] ?? $service->price;
        $data['status'] = 'pending';

        ServiceBooking::create($data);
        ActivityLog::record('booked service', 'services', "{$service->name} for {$data['customer_name']}");

        return back()->with('success', "Booking {$data['code']} created for {$service->name}.");
    }

    public function setBookingStatus(Request $request, ServiceBooking $serviceBooking)
    {
        $request->validate(['status' => 'required|in:pending,confirmed,completed,cancelled']);

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

        return back()->with('success', "Booking {$serviceBooking->code} marked {$request->status}.");
    }

    public function markBookingPaid(Request $request, ServiceBooking $serviceBooking)
    {
        $request->validate(['method' => 'required|in:cash,card,transfer,pos']);

        if ($serviceBooking->paid) {
            return back()->with('success', "Booking {$serviceBooking->code} is already paid.");
        }

        Payment::create([
            'code' => 'PAY-' . strtoupper(Str::random(6)),
            'payable_type' => 'service',
            'payable_id' => $serviceBooking->id,
            'customer_id' => $serviceBooking->customer_id,
            'amount' => $serviceBooking->amount,
            'method' => $request->method,
            'received_by' => auth()->id(),
            'paid_at' => now(),
        ]);

        $serviceBooking->update(['paid' => true]);
        ActivityLog::record('service payment', 'services', $serviceBooking->code);

        return back()->with('success', "Payment recorded for {$serviceBooking->code}.");
    }

    private function validateService(Request $request): array
    {
        return $request->validate([
            'name' => 'required|string|max:120',
            'category' => 'required|in:' . implode(',', self::CATEGORIES),
            'description' => 'nullable|string',
            'price' => 'nullable|numeric|min:0',
            'duration_minutes' => 'nullable|integer|min:5',
            'capacity' => 'nullable|integer|min:1',
        ]);
    }
}
