<?php

namespace App\Controllers;

use App\Models\HotelServiceModel;
use Config\Lookups;

/**
 * Manages the real Services/Extras catalog the New Booking wizard's Add
 * Services step picks from (see CreateHotelServicesTable's doc comment)
 * — same "empty by default, hotel configures its own" pattern as Room
 * Types and Menu Items, not a hardcoded list.
 */
class ServiceCatalogController extends BaseController
{
    public function index()
    {
        $lookups = new Lookups();

        $filters = [
            'q'        => trim((string) $this->request->getGet('q')),
            'category' => $this->request->getGet('category') ?: '',
            'status'   => $this->request->getGet('status') ?: '',
        ];

        // One model instance carried through the whole filter chain and
        // into paginate() — its ->pager is only populated on the exact
        // instance that ran paginate(), so a second `new` here would
        // hand the view a pager that was never actually run.
        $model = (new HotelServiceModel())->orderBy('category')->orderBy('name');

        if ($filters['q'] !== '') {
            $model->like('name', $filters['q']);
        }

        if ($filters['category'] !== '') {
            $model->where('category', $filters['category']);
        }

        if ($filters['status'] === 'active') {
            $model->where('is_active', 1);
        } elseif ($filters['status'] === 'inactive') {
            $model->where('is_active', 0);
        }

        $perPage = (int) ($this->request->getGet('per_page') ?: 10);
        $perPage = in_array($perPage, [10, 25, 50], true) ? $perPage : 10;

        $services = $model->paginate($perPage);

        return view('service_catalog/index', [
            'pageTitle'    => 'Services & Extras',
            'pageSubtitle' => 'Manage the add-ons staff can offer during New Booking.',
            'services'     => $services,
            'pager'        => $model->pager,
            'perPage'      => $perPage,
            'filters'      => $filters,
            'lookups'      => $lookups,
            'stats'        => [
                'total'      => (new HotelServiceModel())->countAllResults(),
                'active'     => (new HotelServiceModel())->where('is_active', 1)->countAllResults(),
                'inactive'   => (new HotelServiceModel())->where('is_active', 0)->countAllResults(),
                'categories' => count($lookups->serviceCategories),
            ],
        ]);
    }

    public function new()
    {
        return view('service_catalog/form', [
            'pageTitle' => 'New Service',
            'service'   => null,
            'lookups'   => new Lookups(),
        ]);
    }

    public function create()
    {
        $model = new HotelServiceModel();
        $data  = $this->collectInput();

        if (! $model->insert($data)) {
            return $this->redirectWithModelErrors($model);
        }

        $this->logActivity('services', 'Added service "' . $data['name'] . '".');

        return redirect()->to('services')->with('success', 'Service added.');
    }

    public function edit(int $id)
    {
        $service = (new HotelServiceModel())->find($id);

        if ($service === null) {
            return redirect()->to('services')->with('error', 'Service not found.');
        }

        return view('service_catalog/form', [
            'pageTitle' => 'Edit Service',
            'service'   => $service,
            'lookups'   => new Lookups(),
        ]);
    }

    public function update(int $id)
    {
        $model = new HotelServiceModel();

        if ($model->find($id) === null) {
            return redirect()->to('services')->with('error', 'Service not found.');
        }

        $data = $this->collectInput();

        if (! $model->update($id, $data)) {
            return $this->redirectWithModelErrors($model);
        }

        $this->logActivity('services', 'Updated service "' . $data['name'] . '".');

        return redirect()->to('services')->with('success', 'Service updated.');
    }

    public function toggleActive(int $id)
    {
        $model   = new HotelServiceModel();
        $service = $model->find($id);

        if ($service === null) {
            return redirect()->to('services')->with('error', 'Service not found.');
        }

        $model->update($id, ['is_active' => $service->is_active ? 0 : 1]);
        $this->logActivity('services', ($service->is_active ? 'Deactivated' : 'Activated') . ' service "' . $service->name . '".');

        return redirect()->to('services')->with('success', 'Service updated.');
    }

    public function delete(int $id)
    {
        $model   = new HotelServiceModel();
        $service = $model->find($id);

        if ($service === null) {
            return redirect()->to('services')->with('error', 'Service not found.');
        }

        // Past bookings that selected this service keep their own
        // snapshotted name/price (see booking_service_items) — deleting
        // the catalog entry never rewrites their history, so there's no
        // "in use" guard needed here unlike Room Types.
        $model->delete($id);
        $this->logActivity('services', 'Deleted service "' . $service->name . '".');

        return redirect()->to('services')->with('success', 'Service deleted.');
    }

    private function collectInput(): array
    {
        return [
            'name'        => $this->request->getPost('name'),
            'description' => $this->request->getPost('description') ?: null,
            'category'    => $this->request->getPost('category') ?: 'other',
            'price'       => parse_money($this->request->getPost('price')),
            'unit_label'  => $this->request->getPost('unit_label') ?: 'flat',
            'is_active'   => $this->request->getPost('is_active') ? 1 : 0,
        ];
    }
}
