<?php
class CarnetController extends Controller
{
    public function index(Request $request): void
    {
        $this->view('carnets/index', [
            'title'       => lang('cards.all_carnets'),
            'breadcrumbs' => [
                ['label' => lang('cards.carnets'), 'url' => '/carnets'],
                ['label' => lang('cards.all_carnets')],
            ],
        ]);
    }

    public function create(Request $request): void
    {
        $db = $this->db();
        $carnetTypes = $db->fetchAll("SELECT * FROM carnet_types WHERE is_active = 1 ORDER BY name_en");

        $this->view('carnets/create', [
            'title'       => lang('cards.issue_carnet'),
            'breadcrumbs' => [
                ['label' => lang('cards.carnets'), 'url' => '/carnets'],
                ['label' => lang('cards.issue_carnet')],
            ],
            'carnetTypes' => $carnetTypes,
        ]);
    }

    public function store(Request $request): void
    {
        if (!CSRF::validate($request->csrfToken())) {
            $this->json(['success' => false, 'message' => 'Invalid CSRF token'], 403);
            return;
        }

        $validator = new Validator($request->all(), [
            'carnet_type_id' => 'required|integer|exists:carnet_types,id',
            'member_id'      => 'required|integer|exists:members,id',
        ]);

        if ($validator->fails()) {
            $this->json(['success' => false, 'errors' => $validator->errors()], 422);
            return;
        }

        $data = $validator->validated();
        $db = $this->db();

        $carnetType = $db->fetchOne("SELECT * FROM carnet_types WHERE id = ?", [$data['carnet_type_id']]);
        $carnetNumber = SequenceGenerator::next('carnet_number');

        $expiryDate = null;
        if ($carnetType['validity_days']) {
            $expiryDate = date('Y-m-d', strtotime("+{$carnetType['validity_days']} days"));
        }

        $id = $db->insert('carnets', [
            'carnet_number'    => $carnetNumber,
            'carnet_type_id'   => $data['carnet_type_id'],
            'member_id'        => $data['member_id'],
            'purchase_date'    => date('Y-m-d'),
            'activation_date'  => date('Y-m-d'),
            'expiry_date'      => $expiryDate,
            'total_entries'    => $carnetType['max_entries'],
            'used_entries'     => 0,
            'remaining_entries'=> $carnetType['max_entries'],
            'status'           => 'active',
            'price_paid'       => $carnetType['price'],
            'created_by'       => Auth::id(),
        ]);

        $this->audit('create', 'carnets', $id, "Carnet issued: {$carnetNumber}");

        $this->json([
            'success'  => true,
            'message'  => lang('cards.carnet_issued'),
            'redirect' => '/carnets/show/' . $id,
        ]);
    }

    public function show(Request $request): void
    {
        $id = (int)$request->routeParam('id');
        $db = $this->db();

        $carnet = $db->fetchOne(
            "SELECT c.*, ct.name_en AS type_name_en, ct.name_ar AS type_name_ar, ct.max_entries AS type_max,
                    m.membership_number, m.full_name_en AS member_name_en, m.full_name_ar AS member_name_ar, m.primary_phone
             FROM carnets c
             JOIN carnet_types ct ON c.carnet_type_id = ct.id
             JOIN members m ON c.member_id = m.id
             WHERE c.id = ?", [$id]
        );

        if (!$carnet) {
            $this->abort(404, 'Carnet not found');
        }

        $entries = $db->fetchAll(
            "SELECT ce.*, f.name_en AS facility_name_en, f.name_ar AS facility_name_ar
             FROM carnet_entries ce
             LEFT JOIN facilities f ON ce.facility_id = f.id
             WHERE ce.carnet_id = ?
             ORDER BY ce.entry_date DESC, ce.entry_time DESC", [$id]
        );

        $this->view('carnets/show', [
            'title'       => lang('cards.carnet_details'),
            'breadcrumbs' => [
                ['label' => lang('cards.carnets'), 'url' => '/carnets'],
                ['label' => $carnet['carnet_number']],
            ],
            'carnet'  => $carnet,
            'entries' => $entries,
        ]);
    }

    public function recordEntry(Request $request): void
    {
        if (!CSRF::validate($request->csrfToken())) {
            $this->json(['success' => false, 'message' => 'Invalid CSRF token'], 403);
            return;
        }

        $id = (int)$request->routeParam('id');
        $db = $this->db();

        $carnet = $db->fetchOne("SELECT * FROM carnets WHERE id = ? AND status = 'active'", [$id]);
        if (!$carnet) {
            $this->json(['success' => false, 'message' => lang('cards.carnet_not_active')], 422);
            return;
        }

        if ($carnet['remaining_entries'] <= 0) {
            $this->json(['success' => false, 'message' => lang('cards.carnet_exhausted')], 422);
            return;
        }

        if ($carnet['expiry_date'] && $carnet['expiry_date'] < date('Y-m-d')) {
            $this->json(['success' => false, 'message' => lang('cards.carnet_expired')], 422);
            return;
        }

        $facilityId = $request->post('facility_id') ? (int)$request->post('facility_id') : null;
        $entryNumber = $carnet['used_entries'] + 1;

        $entryId = $db->insert('carnet_entries', [
            'carnet_id'    => $id,
            'entry_number' => $entryNumber,
            'entry_date'   => date('Y-m-d'),
            'entry_time'   => date('H:i:s'),
            'facility_id'  => $facilityId,
            'used_by_member_id' => $carnet['member_id'],
            'recorded_by'  => Auth::id(),
            'notes'        => $request->post('notes', ''),
        ]);

        // The DB trigger handles updating used_entries/remaining_entries on carnets table

        $this->audit('create', 'carnet_entries', $entryId, "Carnet entry #{$entryNumber} recorded for carnet {$carnet['carnet_number']}");

        $this->json(['success' => true, 'message' => lang('cards.entry_recorded') . " (#{$entryNumber})"]);
    }

    public function voidEntry(Request $request): void
    {
        if (!CSRF::validate($request->csrfToken())) {
            $this->json(['success' => false, 'message' => 'Invalid CSRF token'], 403);
            return;
        }

        $carnetId = (int)$request->routeParam('id');
        $entryId  = (int)$request->routeParam('entryId');
        $reason   = trim($request->post('reason', ''));

        $db = $this->db();
        $entry = $db->fetchOne("SELECT * FROM carnet_entries WHERE id = ? AND carnet_id = ? AND is_voided = 0", [$entryId, $carnetId]);

        if (!$entry) {
            $this->json(['success' => false, 'message' => 'Entry not found or already voided'], 404);
            return;
        }

        $db->update('carnet_entries', [
            'is_voided'   => 1,
            'voided_by'   => Auth::id(),
            'voided_at'   => date('Y-m-d H:i:s'),
            'void_reason' => $reason,
        ], 'id = ?', [$entryId]);

        // The DB trigger handles restoring the count on carnets table

        $this->audit('update', 'carnet_entries', $entryId, "Carnet entry voided: {$reason}");

        $this->json(['success' => true, 'message' => lang('cards.entry_voided')]);
    }

    public function types(Request $request): void
    {
        $db = $this->db();
        $types = $db->fetchAll("SELECT * FROM carnet_types ORDER BY name_en");

        $this->view('carnets/types', [
            'title'       => lang('cards.carnet_types'),
            'breadcrumbs' => [
                ['label' => lang('cards.carnets'), 'url' => '/carnets'],
                ['label' => lang('cards.carnet_types')],
            ],
            'types' => $types,
        ]);
    }

    public function storeType(Request $request): void
    {
        if (!CSRF::validate($request->csrfToken())) {
            $this->json(['success' => false, 'message' => 'Invalid CSRF token'], 403);
            return;
        }

        $validator = new Validator($request->all(), [
            'type_code'     => 'required|string|max:20',
            'name_en'       => 'required|string|max:200',
            'name_ar'       => 'required|string|max:200',
            'max_entries'   => 'required|integer|min:1',
            'validity_days' => 'nullable|integer|min:1',
            'price'         => 'required|decimal|min:0',
        ]);

        if ($validator->fails()) {
            $this->json(['success' => false, 'errors' => $validator->errors()], 422);
            return;
        }

        $data = $validator->validated();
        $data['is_active'] = 1;

        $id = $this->db()->insert('carnet_types', $data);
        $this->audit('create', 'carnet_types', $id, "Carnet type created: {$data['name_en']}");

        $this->json(['success' => true, 'message' => lang('common.save') . ' ✓']);
    }

    public function updateType(Request $request): void
    {
        if (!CSRF::validate($request->csrfToken())) {
            $this->json(['success' => false, 'message' => 'Invalid CSRF token'], 403);
            return;
        }

        $id = (int)$request->routeParam('id');
        $validator = new Validator($request->all(), [
            'name_en'       => 'required|string|max:200',
            'name_ar'       => 'required|string|max:200',
            'max_entries'   => 'required|integer|min:1',
            'validity_days' => 'nullable|integer|min:1',
            'price'         => 'required|decimal|min:0',
            'is_active'     => 'nullable|in:0,1',
        ]);

        if ($validator->fails()) {
            $this->json(['success' => false, 'errors' => $validator->errors()], 422);
            return;
        }

        $data = $validator->validated();
        $data['is_active'] = $data['is_active'] ?? 1;
        $db = $this->db();
        $old = $db->fetchOne("SELECT * FROM carnet_types WHERE id = ?", [$id]);
        $db->update('carnet_types', $data, 'id = ?', [$id]);
        $this->audit('update', 'carnet_types', $id, "Carnet type updated", $old, $data);

        $this->json(['success' => true, 'message' => lang('common.save') . ' ✓']);
    }
}