<?php

namespace Modules\Loyalty\Controllers;

use core\Controller;
use core\Auth;
use core\Database;
use core\Security;

class MembershipController extends Controller
{
    public function __construct()
    {
        parent::__construct();
    }

    public function index(): void
    {
        $this->requirePermission('loyalty_memberships_view');

        $db = Database::getInstance();
        $status = $this->request->get('status', '');
        $page = max(1, (int)$this->request->get('page', 1));
        $perPage = PAGINATION_LIMIT;

        $query = $db->table('customer_memberships m')
            ->select('m.*, c.first_name as customer_first_name, c.last_name as customer_last_name,
                      c.email as customer_email, c.phone as customer_phone,
                      mt.name as tier_name, mt.priority as tier_level')
            ->leftJoin('customers c', 'm.customer_id', '=', 'c.id')
            ->leftJoin('membership_tiers mt', 'm.tier_id', '=', 'mt.id');

        if (!empty($status)) {
            $query->where('m.status', $status);
        }

        $memberships = $query->orderBy('m.created_at', 'DESC')->paginate($perPage, $page);

        $this->view('Loyalty/membership/index', [
            'title' => 'Memberships',
            'breadcrumb' => ['Memberships' => url('membership')],
            'memberships' => $memberships,
            'status' => $status,
        ]);
    }

    public function tiers(): void
    {
        $this->requirePermission('loyalty_tiers_view');

        $db = Database::getInstance();
        $tiers = $db->table('membership_tiers')
            ->orderBy('priority', 'ASC')
            ->get();

        $this->view('Loyalty/membership/tiers', [
            'title' => 'Membership Tiers',
            'breadcrumb' => [
                'Memberships' => url('membership'),
                'Tiers' => url('membership/tiers'),
            ],
            'tiers' => $tiers,
        ]);
    }

    public function storeTier(): void
    {
        $this->requirePermission('loyalty_tiers_manage');

        $validated = $this->validate([
            'name' => 'required|max_length:100',
            'tier_level' => 'required|integer|min:1|max:10',
            'min_points' => 'integer|min:0',
            'benefits' => 'max_length:2000',
            'is_active' => 'in:0,1',
        ]);

        $validated['is_active'] = $validated['is_active'] ?? 1;
        $validated['priority'] = $validated['tier_level'];
        unset($validated['tier_level']);
        $id = $this->request->post('id');

        if (!empty($id)) {
            $existing = Database::getInstance()->table('membership_tiers')->find($id);
            if (!$existing) {
                $this->redirectWith(url('membership/tiers'), 'error', 'Tier not found.');
            }
            $oldValues = (array)$existing;
            Database::getInstance()->table('membership_tiers')->where('id', $id)->update($validated);
            $this->logAudit('update', 'membership_tiers', $id, $oldValues, $validated);
            $msg = 'Tier updated successfully.';
        } else {
            $id = Database::getInstance()->table('membership_tiers')->insert($validated);
            $this->logAudit('create', 'membership_tiers', $id, null, $validated);
            $msg = 'Tier created successfully.';
        }

        $this->logActivity('manage_tier', $msg . ': ' . $validated['name']);
        $this->redirectWith(url('membership/tiers'), 'success', $msg);
    }

    public function assign(): void
    {
        $this->requirePermission('loyalty_memberships_assign');

        $db = Database::getInstance();
        $customers = $db->table('customers')
            ->where('deleted_at', 'IS', null)
            ->orderBy('first_name', 'ASC')
            ->get();

        $tiers = $db->table('membership_tiers')
            ->where('is_active', 1)
            ->orderBy('priority', 'ASC')
            ->get();

        $this->view('Loyalty/membership/assign', [
            'title' => 'Assign Membership',
            'breadcrumb' => [
                'Memberships' => url('membership'),
                'Assign' => url('membership/assign'),
            ],
            'customers' => $customers,
            'tiers' => $tiers,
        ]);
    }

    public function store(): void
    {
        $this->requirePermission('loyalty_memberships_assign');

        $validated = $this->validate([
            'customer_id' => 'required|integer',
            'tier_id' => 'required|integer',
            'start_date' => 'required|date',
            'end_date' => 'date',
        ]);

        $exists = Database::getInstance()->table('customer_memberships')
            ->where('customer_id', $validated['customer_id'])
            ->where('status', 'active')
            ->first();

        if ($exists) {
            $this->redirectWith(url('membership/assign'), 'error', 'Customer already has an active membership.');
        }

        $validated['status'] = 'active';
        $membershipId = Database::getInstance()->table('customer_memberships')->insert($validated);
        $this->logActivity('assign', 'Assigned membership to customer #' . $validated['customer_id']);
        $this->logAudit('create', 'memberships', $membershipId, null, $validated);

        $this->redirectWith(url('membership'), 'success', 'Membership assigned successfully.');
    }

    public function cancel(int $id): void
    {
        $this->requirePermission('loyalty_memberships_cancel');

        $db = Database::getInstance();
        $membership = $db->table('customer_memberships')->find($id);
        if (!$membership) {
            $this->redirectWith(url('membership'), 'error', 'Membership not found.');
        }

        $db->table('customer_memberships')->where('id', $id)->update([
            'status' => 'cancelled',
            'cancelled_at' => date(DATE_TIME_FORMAT),
        ]);

        $this->logActivity('cancel', 'Cancelled membership #' . $id);
        $this->logAudit('update', 'memberships', $id, (array)$membership, ['status' => 'cancelled']);

        $this->redirectWith(url('membership'), 'success', 'Membership cancelled.');
    }
}
