<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Models\DiscountModel;
use App\Models\CategoryModel;
use App\Models\MenuItemModel;
use App\Helpers\ActivityLogger;
use Core\Request;

final class DiscountController extends BaseController
{
    private DiscountModel $model;

    public function __construct()
    {
        parent::__construct();
        $this->model = new DiscountModel();
    }

    public function index(array $params = []): void
    {
        $this->requirePermission('discount.view');

        $page  = $this->currentPage();
        $this->view('discounts.index', [
            'pageTitle'   => 'Discount Offers',
            'breadcrumbs' => ['Discount Offers' => null],
            'discounts'   => $this->model->all($page),
            'total'       => $this->model->count(),
            'page'        => $page,
        ]);
    }

    public function create(array $params = []): void
    {
        $this->requirePermission('discount.create');

        $this->view('discounts.form', [
            'pageTitle'   => 'Create Discount',
            'breadcrumbs' => ['Discounts' => url('discounts'), 'Create' => null],
            'discount'    => null,
            'categories'  => (new CategoryModel())->activeList(),
            'menuItems'   => $this->getItemsList(),
        ]);
    }

    public function store(array $params = []): void
    {
        $this->requirePermission('discount.create');
        Request::verifyCsrf();

        $errors = $this->validate();
        if ($errors) {
            $this->flash('error', implode('<br>', $errors));
            $this->redirect('/discounts/create');
        }

        $title     = Request::str('title');
        $appliesTo = Request::post('applies_to', 'order');
        $targetId  = in_array($appliesTo, ['item','category']) ? Request::int('target_id') : null;

        $id = $this->model->create([
            'title'          => $title,
            'discount_type'  => Request::post('discount_type', 'percentage'),
            'discount_value' => Request::float('discount_value'),
            'applies_to'     => $appliesTo,
            'target_id'      => $targetId,
            'min_order_amt'  => Request::float('min_order_amt', 0),
            'max_discount'   => Request::float('max_discount', 0) > 0 ? Request::float('max_discount', 0) : null,
            'starts_at'      => Request::post('starts_at'),
            'expires_at'     => Request::post('expires_at'),
            'is_active'      => Request::bool('is_active', true) ? 1 : 0,
            'created_by'     => \Core\Auth::id(),
        ]);

        ActivityLogger::created('discount', $id, $title);
        $this->flash('success', "Discount <strong>{$title}</strong> created.");
        $this->redirect('/discounts');
    }

    public function edit(array $params = []): void
    {
        $this->requirePermission('discount.edit');

        $discount = $this->model->find((int)$params['id']);
        if (!$discount) { $this->flash('error', 'Discount not found.'); $this->redirect('/discounts'); }

        $this->view('discounts.form', [
            'pageTitle'   => 'Edit Discount',
            'breadcrumbs' => ['Discounts' => url('discounts'), 'Edit' => null],
            'discount'    => $discount,
            'categories'  => (new CategoryModel())->activeList(),
            'menuItems'   => $this->getItemsList(),
        ]);
    }

    public function update(array $params = []): void
    {
        $this->requirePermission('discount.edit');
        Request::verifyCsrf();

        $id       = (int)$params['id'];
        $discount = $this->model->find($id);
        if (!$discount) { $this->flash('error', 'Discount not found.'); $this->redirect('/discounts'); }

        $errors = $this->validate();
        if ($errors) {
            $this->flash('error', implode('<br>', $errors));
            $this->redirect("/discounts/{$id}/edit");
        }

        $title     = Request::str('title');
        $appliesTo = Request::post('applies_to', 'order');
        $targetId  = in_array($appliesTo, ['item','category']) ? Request::int('target_id') : null;

        $this->model->update($id, [
            'title'          => $title,
            'discount_type'  => Request::post('discount_type', 'percentage'),
            'discount_value' => Request::float('discount_value'),
            'applies_to'     => $appliesTo,
            'target_id'      => $targetId,
            'min_order_amt'  => Request::float('min_order_amt', 0),
            'max_discount'   => Request::float('max_discount', 0) > 0 ? Request::float('max_discount', 0) : null,
            'starts_at'      => Request::post('starts_at'),
            'expires_at'     => Request::post('expires_at'),
            'is_active'      => Request::bool('is_active', true) ? 1 : 0,
        ]);

        ActivityLogger::updated('discount', $id, $title);
        $this->flash('success', "Discount <strong>{$title}</strong> updated.");
        $this->redirect('/discounts');
    }

    public function delete(array $params = []): void
    {
        $this->requirePermission('discount.delete');
        Request::verifyCsrf();

        $id       = (int)$params['id'];
        $discount = $this->model->find($id);
        if (!$discount) { $this->flash('error', 'Not found.'); $this->redirect('/discounts'); }

        $this->model->delete($id);
        ActivityLogger::deleted('discount', $id, $discount['title']);
        $this->flash('success', 'Discount deleted.');
        $this->redirect('/discounts');
    }

    private function validate(): array
    {
        $errors = [];
        if (!Request::str('title'))            $errors[] = 'Title is required.';
        $val  = Request::float('discount_value');
        $type = Request::post('discount_type');
        if ($val <= 0)                         $errors[] = 'Discount value must be greater than 0.';
        if ($type === 'percentage' && $val > 100) $errors[] = 'Percentage cannot exceed 100%.';
        if (!Request::post('starts_at') || !Request::post('expires_at')) $errors[] = 'Dates are required.';
        elseif (Request::post('expires_at') <= Request::post('starts_at')) $errors[] = 'Expiry must be after start.';
        $appliesTo = Request::post('applies_to');
        if (in_array($appliesTo, ['item','category']) && !Request::int('target_id'))
            $errors[] = 'Please select a target ' . $appliesTo . '.';
        return $errors;
    }

    private function getItemsList(): array
    {
        return $this->db->fetchAll(
            "SELECT mi.id, mi.name, mi.base_price, c.name AS category_name
               FROM menu_items mi
               JOIN categories c ON c.id = mi.category_id
              ORDER BY c.name ASC, mi.name ASC"
        );
    }
}
