<?php

namespace App\Controllers;

use App\Models\RatePlanModel;
use App\Models\RoomTypeModel;

/**
 * Manager-only. Simple date-range rate rules — see RatePlanModel for how
 * they're resolved against a booking's check-in date.
 */
class RatePlanController extends BaseController
{
    /**
     * "Active/Scheduled/Inactive" is a derived status, not a stored
     * column — is_active only tracks manager on/off, so a plan dated in
     * the future is still "Active" in the DB sense but should read as
     * upcoming rather than currently applying. Computed the same way for
     * both the KPI cards and the row badges/filter so they can't drift
     * from each other.
     */
    public function index()
    {
        $today = date('Y-m-d');
        $roomTypes = (new RoomTypeModel())->orderBy('name')->findAll();

        $plans = (new RatePlanModel())->withRoomTypeNames();

        foreach ($plans as $plan) {
            $plan->computed_status = $this->computeStatus($plan, $today);
            $plan->nights = (int) round((strtotime($plan->date_end) - strtotime($plan->date_start)) / 86400) + 1;
        }

        $stats = [
            'total'     => count($plans),
            'active'    => count(array_filter($plans, static fn ($p) => $p->computed_status === 'active')),
            'scheduled' => count(array_filter($plans, static fn ($p) => $p->computed_status === 'scheduled')),
            'inactive'  => count(array_filter($plans, static fn ($p) => $p->computed_status === 'inactive')),
        ];

        $search   = trim((string) $this->request->getGet('q'));
        $status   = $this->request->getGet('status') ?: '';
        $roomTypeId = (int) $this->request->getGet('room_type_id');

        $filtered = array_values(array_filter($plans, static function ($plan) use ($search, $status, $roomTypeId) {
            if ($search !== '' && stripos($plan->name, $search) === false) {
                return false;
            }

            if ($status !== '' && $plan->computed_status !== $status) {
                return false;
            }

            if ($roomTypeId > 0 && ! in_array($roomTypeId, $plan->room_type_ids, true)) {
                return false;
            }

            return true;
        }));

        $perPage = (int) ($this->request->getGet('per_page') ?: 10);
        $perPage = in_array($perPage, [10, 25, 50], true) ? $perPage : 10;
        $total   = count($filtered);
        $totalPages = max(1, (int) ceil($total / $perPage));
        $page    = max(1, min($totalPages, (int) ($this->request->getGet('page') ?: 1)));
        $pageItems = array_slice($filtered, ($page - 1) * $perPage, $perPage);

        return view('rate_plans/index', [
            'pageTitle'  => 'Rate Plans',
            'plans'      => $pageItems,
            'roomTypes'  => $roomTypes,
            'stats'      => $stats,
            'filters'    => ['q' => $search, 'status' => $status, 'room_type_id' => $roomTypeId ?: ''],
            'perPage'    => $perPage,
            'page'       => $page,
            'totalPages' => $totalPages,
            'total'      => $total,
        ]);
    }

    private function computeStatus(object $plan, string $today): string
    {
        if (! $plan->is_active) {
            return 'inactive';
        }

        return $plan->date_start > $today ? 'scheduled' : 'active';
    }

    public function new()
    {
        return view('rate_plans/form', [
            'pageTitle'      => 'New Rate Plan',
            'plan'           => null,
            'roomTypes'      => (new RoomTypeModel())->orderBy('name')->findAll(),
            'selectedTypeIds' => [],
        ]);
    }

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

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

        $planId = $model->getInsertID();
        $model->syncRoomTypes($planId, $this->request->getPost('room_type_ids') ?? []);

        $this->logActivity('rate_plans', 'Created rate plan "' . $data['name'] . '".');

        return redirect()->to('rate-plans')->with('success', 'Rate plan created.');
    }

    public function edit(int $id)
    {
        $model = new RatePlanModel();
        $plan  = $model->find($id);

        if ($plan === null) {
            return redirect()->to('rate-plans')->with('error', 'Rate plan not found.');
        }

        return view('rate_plans/form', [
            'pageTitle'       => 'Edit Rate Plan',
            'plan'            => $plan,
            'roomTypes'       => (new RoomTypeModel())->orderBy('name')->findAll(),
            'selectedTypeIds' => $model->roomTypeIds($id),
        ]);
    }

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

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

        $data = $this->collectInput();

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

        $model->syncRoomTypes($id, $this->request->getPost('room_type_ids') ?? []);

        $this->logActivity('rate_plans', 'Updated rate plan "' . $data['name'] . '".');

        return redirect()->to('rate-plans')->with('success', 'Rate plan updated.');
    }

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

        if ($plan === null) {
            return redirect()->to('rate-plans')->with('error', 'Rate plan not found.');
        }

        $model->delete($id);
        $this->logActivity('rate_plans', 'Deleted rate plan "' . $plan->name . '".');

        return redirect()->to('rate-plans')->with('success', 'Rate plan deleted.');
    }

    private function collectInput(): array
    {
        return [
            'name'             => $this->request->getPost('name'),
            'description'      => $this->request->getPost('description') ?: null,
            'date_start'       => $this->request->getPost('date_start'),
            'date_end'         => $this->request->getPost('date_end'),
            'adjustment_type'  => $this->request->getPost('adjustment_type'),
            'adjustment_value' => $this->request->getPost('adjustment_value'),
            'is_active'        => $this->request->getPost('is_active') ? 1 : 0,
        ];
    }
}
