<?php
class AccessApiController extends Controller
{
    public function pointsDatatable(Request $request): void
    {
        $db = $this->db();
        $rows = $db->fetchAll(
            "SELECT ap.*, f.name_en AS facility_name_en, f.name_ar AS facility_name_ar
             FROM access_points ap
             LEFT JOIN facilities f ON ap.facility_id = f.id
             ORDER BY ap.name_en"
        );
        $this->json([
            'draw' => (int)$request->get('draw', 1),
            'recordsTotal' => count($rows),
            'recordsFiltered' => count($rows),
            'data' => $rows,
        ]);
    }

    public function rulesDatatable(Request $request): void
    {
        $db = $this->db();
        $rows = $db->fetchAll(
            "SELECT acr.*, ap.name_en AS point_name_en, ap.name_ar AS point_name_ar,
                    mt.name_en AS memtype_name_en, mt.name_ar AS memtype_name_ar
             FROM access_control_rules acr
             JOIN access_points ap ON acr.access_point_id = ap.id
             LEFT JOIN membership_types mt ON acr.membership_type_id = mt.id
             ORDER BY acr.priority DESC, acr.id"
        );
        $this->json([
            'draw' => (int)$request->get('draw', 1),
            'recordsTotal' => count($rows),
            'recordsFiltered' => count($rows),
            'data' => $rows,
        ]);
    }

    public function logDatatable(Request $request): void
    {
        $db = $this->db();
        $draw   = (int)$request->get('draw', 1);
        $start  = (int)$request->get('start', 0);
        $length = (int)$request->get('length', 25);
        $search = $request->get('search')['value'] ?? '';

        $dateFrom  = $request->get('date_from', date('Y-m-d'));
        $dateTo    = $request->get('date_to', date('Y-m-d'));
        $direction = $request->get('direction', '');
        $granted   = $request->get('granted', '');

        $where = "DATE(mal.access_time) BETWEEN ? AND ?";
        $params = [$dateFrom, $dateTo];

        if ($direction) {
            $where .= " AND mal.direction = ?";
            $params[] = $direction;
        }
        if ($granted !== '') {
            $where .= " AND mal.granted = ?";
            $params[] = (int)$granted;
        }
        if ($search) {
            $where .= " AND (m.full_name_en LIKE ? OR m.full_name_ar LIKE ? OR m.membership_number LIKE ? OR mc.card_number LIKE ?)";
            $s = "%{$search}%";
            $params = array_merge($params, [$s, $s, $s, $s]);
        }

        $totalFiltered = (int)$db->fetchColumn(
            "SELECT COUNT(*)
             FROM member_access_log mal
             LEFT JOIN members m ON mal.member_id = m.id
             LEFT JOIN member_cards mc ON mal.card_id = mc.id
             WHERE {$where}", $params
        );

        $rows = $db->fetchAll(
            "SELECT mal.id, mal.direction, mal.access_time, mal.access_method, mal.granted, mal.denial_reason,
                    ap.name_en AS point_name_en, ap.name_ar AS point_name_ar, ap.point_type,
                    m.membership_number, m.full_name_en AS member_name_en, m.full_name_ar AS member_name_ar,
                    mc.card_number,
                    mt.name_en AS memtype_name_en
             FROM member_access_log mal
             JOIN access_points ap ON mal.access_point_id = ap.id
             LEFT JOIN members m ON mal.member_id = m.id
             LEFT JOIN member_cards mc ON mal.card_id = mc.id
             LEFT JOIN membership_types mt ON m.membership_type_id = mt.id
             WHERE {$where}
             ORDER BY mal.access_time DESC
             LIMIT " . (int)$length . " OFFSET " . (int)$start,
            $params
        );

        $this->json([
            'draw'            => $draw,
            'recordsTotal'    => $totalFiltered,
            'recordsFiltered' => $totalFiltered,
            'data'            => $rows,
        ]);
    }

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

        $validator = new Validator($request->all(), [
            'access_point_id' => 'required|integer|exists:access_points,id',
            'member_id'       => 'nullable|integer',
            'card_id'         => 'nullable|integer',
            'guest_pass_id'   => 'nullable|integer',
            'direction'       => 'required|in:entry,exit',
            'access_method'   => 'required|in:card,barcode,qr,rfid,fingerprint,face,manual',
        ]);

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

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

        $granted = true;
        $denialReason = null;

        if ($data['member_id']) {
            $member = $db->fetchOne("SELECT id, status, membership_type_id FROM members WHERE id = ? AND is_deleted = 0", [$data['member_id']]);
            if (!$member) {
                $granted = false;
                $denialReason = 'Member not found';
            } elseif ($member['status'] !== 'active' && $member['status'] !== 'frozen') {
                $granted = false;
                $denialReason = 'Member status: ' . $member['status'];
            }
        }

        $id = $db->insert('member_access_log', [
            'access_point_id' => $data['access_point_id'],
            'member_id'       => $data['member_id'] ?? null,
            'card_id'         => $data['card_id'] ?? null,
            'guest_pass_id'   => $data['guest_pass_id'] ?? null,
            'direction'       => $data['direction'],
            'access_method'   => $data['access_method'],
            'granted'         => $granted ? 1 : 0,
            'denial_reason'   => $denialReason,
        ]);

        $this->json([
            'success' => true,
            'granted' => $granted,
            'denial_reason' => $denialReason,
            'message' => $granted ? 'Access granted' : "Access denied: {$denialReason}",
        ]);
    }
}