<?php

namespace App\DataTables;

use App\Models\MemberAccessLog;
use Carbon\Carbon;
use Illuminate\Support\Str;
use Yajra\DataTables\Services\DataTable;

class MemberQrScanDataTable extends DataTable
{
    public function dataTable($query)
    {
        return datatables()
            ->eloquent($query)
            ->addColumn('member_name', function (MemberAccessLog $row) {
                if (! $row->member_id || ! $row->member) {
                    return '<span class="text-muted">—</span>';
                }
                $link = route('admin.members.show', $row->member_id);

                return '<a href="' . $link . '" class="fw-medium text-primary">' . e($row->member->name) . '</a>';
            })
            ->addColumn('member_phone', function (MemberAccessLog $row) {
                return e($row->member?->phone ?? '—');
            })
            ->addColumn('guard_name', function (MemberAccessLog $row) {
                return e($row->scannedBy?->name ?? '—');
            })
            ->addColumn('result', function (MemberAccessLog $row) {
                $granted = $row->result === 'granted';

                return $granted
                    ? '<span class="badge bg-success-subtle text-success">' . e(__('dashboard.granted')) . '</span>'
                    : '<span class="badge bg-danger-subtle text-danger">' . e(__('dashboard.denied')) . '</span>';
            })
            ->addColumn('deny_reason', fn (MemberAccessLog $row) => $row->deny_reason ? e($row->deny_reason) : '—')
            ->addColumn('token', fn (MemberAccessLog $row) => e(Str::limit((string) $row->token, 16)))
            ->addColumn('scanned_at', fn (MemberAccessLog $row) => $row->scanned_at?->format('Y-m-d H:i:s') ?? '—')
            ->addColumn('action', fn (MemberAccessLog $row) => view('admin.qr-codes.member-scans.partials.actions', ['row' => $row])->render())
            ->rawColumns(['member_name', 'result', 'action'])
            ->filterColumn('member_name', function ($q, $keyword) {
                $q->whereHas('member', fn ($mq) => $mq->where('name', 'like', '%' . $keyword . '%'));
            })
            ->filterColumn('member_phone', function ($q, $keyword) {
                $q->whereHas('member', fn ($mq) => $mq->where('phone', 'like', '%' . $keyword . '%'));
            })
            ->filterColumn('guard_name', function ($q, $keyword) {
                $q->whereHas('scannedBy', fn ($sq) => $sq->where('name', 'like', '%' . $keyword . '%'));
            })
            ->orderColumn('member_name', false)
            ->orderColumn('member_phone', false)
            ->orderColumn('guard_name', false)
            ->orderColumn('result', false)
            ->orderColumn('deny_reason', false)
            ->orderColumn('token', false)
            ->orderColumn('action', false);
    }

    public function query(MemberAccessLog $model)
    {
        $q = $model->newQuery()
            ->where('action', 'scan')
            ->with(['member', 'scannedBy']);

        $filter = request()->input('filter', []);

        if (! empty($filter['period']) && $filter['period'] !== 'all' && $filter['period'] !== '') {
            $now = Carbon::now();
            switch ($filter['period']) {
                case 'today':
                    $q->whereDate('scanned_at', $now->toDateString());
                    break;
                case 'week':
                    $q->whereBetween('scanned_at', [
                        $now->copy()->startOfWeek()->toDateTimeString(),
                        $now->copy()->endOfWeek()->toDateTimeString(),
                    ]);
                    break;
                case 'month':
                    $q->whereMonth('scanned_at', $now->month)
                        ->whereYear('scanned_at', $now->year);
                    break;
                case 'year':
                    $q->whereYear('scanned_at', $now->year);
                    break;
            }
        }

        if (! empty($filter['result']) && in_array($filter['result'], ['granted', 'denied'], true)) {
            $q->where('result', $filter['result']);
        }

        if (! empty($filter['scanned_at']) && is_array($filter['scanned_at'])) {
            $from = $filter['scanned_at']['from'] ?? null;
            $to = $filter['scanned_at']['to'] ?? null;
            if ($from) {
                $q->whereDate('scanned_at', '>=', $from);
            }
            if ($to) {
                $q->whereDate('scanned_at', '<=', $to);
            }
        }

        return $q;
    }

    public function html()
    {
        $data = $this->getExportData();

        return $this->builder()
            ->setTableId('member-qr-scans-table')
            ->columns($this->getColumns())
            ->minifiedAjax()
            ->ajax([
                'url'  => route('admin.qr-codes.member-scans.datatable'),
                'data' => dtFilters($data['exportFilters']),
            ])
            ->orderBy(7, 'desc')
            ->language([
                'url' => asset('/dashboard_assets/js/datatable/datatables/langs/' . app()->getLocale() . '.json'),
            ])
            ->scrollX(true)
            ->dom('Blfrtip')
            ->parameters([
                'buttons' => dtButtons([]),
            ] + dtLength(10));
    }

    protected function getColumns(): array
    {
        return [
            addCol('id', __('dashboard.id'), true, false, true, true),
            addCol('member_name', __('dashboard.member'), false, true, true, true),
            addCol('member_phone', __('dashboard.phone'), false, true, true, true),
            addCol('guard_name', __('dashboard.guard'), false, true, true, true),
            addCol('result', __('dashboard.scan_result'), false, false, true, true),
            addCol('deny_reason', __('dashboard.deny_reason'), false, false, true, true),
            addCol('token', __('dashboard.token'), false, false, true, true),
            addCol('scanned_at', __('dashboard.scanned_at'), true, false, true, true),
            computedCol('action', __('dashboard.actions')),
        ];
    }

    protected function filename(): string
    {
        return 'MemberQrScans_' . date('YmdHis');
    }

    /**
     * @return array{exportFilters: array<string, string>}
     */
    private function getExportData(): array
    {
        return [
            'exportFilters' => [
                'period'            => '.report',
                'result'            => '#member-scan-result-filter',
                'scanned_at:range'  => '#member-scan-range-date',
            ],
        ];
    }
}
