<?php
namespace App\Controllers\Backend;

use App\Controllers\BaseController;
use App\Models\PromotionModel;
use App\Models\EventModel;

class PromotionsController extends BaseController
{
    public function index()
    {
        $promoModel = new PromotionModel();
        $data = [
            'promotions' => $promoModel->select('promotions.*, events.name as event_name')
                                      ->join('events', 'events.id = promotions.event_id', 'left')
                                      ->paginate(10),
            'pager'      => $promoModel->pager,
            'pageTitle'  => lang('Admin/Promotions.pageTitle'),
        ];
        return view('backend/promotions/index', $data);
    }

    public function new()
    {
        $data = [
            'events' => (new EventModel())->where('end_date >=', date('Y-m-d'))->where('is_active', 1)->findAll(),
            'pageTitle' => lang('Admin/Promotions.newPromotion'),
        ];
        return view('backend/promotions/new', $data);
    }

    public function create()
    {
        if (!$this->validate($this->getValidationRules())) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }
        
        (new PromotionModel())->save($this->prepareSaveData());

        return redirect()->to(route_to('admin.promotions.index'))->with('success', lang('Admin/Promotions.createSuccess'));
    }
    
    public function edit($id = null)
    {
        $promo = (new PromotionModel())->find($id);
        if (!$promo) {
            return redirect()->back()->with('error', lang('Admin/Promotions.errorNotFound'));
        }

        $data = [
            'promotion' => $promo,
            'events' => (new EventModel())->where('end_date >=', date('Y-m-d'))->where('is_active', 1)->findAll(),
            'pageTitle' => lang('Admin/Promotions.editPromotion', [$promo->name]),
        ];
        return view('backend/promotions/edit', $data);
    }
    
    public function update($id = null)
    {
        if (!$this->validate($this->getValidationRules($id))) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }
        
        $dataToSave = $this->prepareSaveData();
        $dataToSave['id'] = $id;

        (new PromotionModel())->save($dataToSave);
        
        return redirect()->to(route_to('admin.promotions.index'))->with('success', lang('Admin/Promotions.updateSuccess'));
    }

    public function delete($id = null)
    {
        (new PromotionModel())->delete($id);
        return redirect()->to(route_to('admin.promotions.index'))->with('success', lang('Admin/Promotions.deleteSuccess'));
    }

    private function prepareSaveData(): array
    {
        $discountType = $this->request->getPost('discount_type');
        
        return [
            'event_id'         => $this->request->getPost('event_id'),
            'name'             => $this->request->getPost('name'),
            'code'             => strtoupper($this->request->getPost('code')),
            'description'      => $this->request->getPost('description'),
            'quota'            => (int)$this->request->getPost('quota'),
            'min_quantity'     => (int)$this->request->getPost('min_quantity'),
            'max_quantity'     => $this->request->getPost('max_quantity') ?: null,
            'min_amount'       => (float)$this->request->getPost('min_amount'),
            'max_amount'       => $this->request->getPost('max_amount') ?: null,
            'discount_amount'  => ($discountType === 'fixed') ? (float)$this->request->getPost('discount_amount') : 0,
            'discount_percent' => ($discountType === 'percent') ? (float)$this->request->getPost('discount_percent') : 0,
            'start_date'       => $this->request->getPost('start_date'),
            'end_date'         => $this->request->getPost('end_date'),
            'is_active'        => (bool)$this->request->getPost('is_active'),
        ];
    }

    private function getValidationRules(int $id = null): array
    {
        $eventEndDate = $this->request->getPost('end_date');
        return [
            'event_id'     => 'required|is_natural_no_zero',
            'name'         => 'required|string|max_length[100]',
            'code'         => "required|alpha_dash|is_unique[promotions.code,event_id,{$this->request->getPost('event_id')},id,{$id}]",
            'quota'        => 'required|is_natural',
            'min_quantity' => 'required|is_natural',
            'max_quantity' => 'permit_empty|is_natural|greater_than_equal_to[' . ($this->request->getPost('min_quantity') ?? 0) . ']',
            'min_amount'   => 'required|numeric',
            'max_amount'   => 'permit_empty|numeric|greater_than_equal_to[' . ($this->request->getPost('min_amount') ?? 0) . ']',
            'discount_amount'  => 'permit_empty|numeric',
            'discount_percent' => 'permit_empty|numeric|less_than_equal_to[100]',
            'start_date' => "required|valid_date|after_or_equal_to_field[{$eventEndDate}]",
            'end_date' => "required|valid_date|after_or_equal_to_field[start_date]",
        ];
    }
}