<?php

namespace App\Repositories\Admin\Member;

use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;

final class AdminMemberRepository
{
    public function paginateMembers(array $filters, int $perPage = 30): LengthAwarePaginator
    {
        $q = DB::table('mem_info as m');

        $qf = (string)($filters['qf'] ?? '');          // mem_no|name|email|phone (또는 ''/all)
        $keyword = trim((string)($filters['q'] ?? ''));
        $phoneEnc = (string)($filters['phone_enc'] ?? '');

        if ($keyword !== '') {
            $digits = preg_replace('/\D+/', '', $keyword) ?? '';

            switch ($qf) {
                case 'mem_no':
                    if ($digits !== '' && ctype_digit($digits)) {
                        $q->where('m.mem_no', (int)$digits);
                    } else {
                        $q->whereRaw('1=0'); // 잘못된 입력이면 결과 없음
                    }
                    break;

                case 'name':
                    $q->where('m.name', 'like', "%{$keyword}%");
                    break;

                case 'email':
                    $q->where('m.email', 'like', "%{$keyword}%");
                    break;

                case 'phone':
                    if ($phoneEnc !== '') {
                        $q->where('m.cell_phone', $phoneEnc);
                    } else {
                        $q->whereRaw('1=0'); // phone_enc 없으면 매칭 불가
                    }
                    break;

                default:
                    // qf가 없거나(all)일 때: 기존 통합 검색 + phone_enc 있으면 OR로 포함
                    $q->where(function ($w) use ($keyword, $digits, $phoneEnc) {
                        if ($digits !== '' && ctype_digit($digits)) {
                            $w->orWhere('m.mem_no', (int)$digits);
                        }

                        $w->orWhere('m.name', 'like', "%{$keyword}%")
                            ->orWhere('m.email', 'like', "%{$keyword}%");

                        if ($phoneEnc !== '') {
                            $w->orWhere('m.cell_phone', $phoneEnc);
                        }
                    });
                    break;
            }
        }

        // stat_3
        $stat3 = (string)($filters['stat_3'] ?? '');
        if ($stat3 !== '') {
            $q->where('m.stat_3', $stat3);
        }

        // date range
        $dateFrom = trim((string)($filters['date_from'] ?? ''));
        if ($dateFrom !== '') {
            $q->where('m.dt_reg', '>=', $dateFrom.' 00:00:00');
        }
        $dateTo = trim((string)($filters['date_to'] ?? ''));
        if ($dateTo !== '') {
            $q->where('m.dt_reg', '<=', $dateTo.' 23:59:59');
        }

        $q->orderByDesc('m.mem_no');

        return $q->select([
            'm.mem_no',
            'm.stat_1','m.stat_2','m.stat_3','m.stat_4','m.stat_5',
            'm.name','m.birth','m.gender','m.native',
            'm.cell_corp','m.cell_phone','m.email',
            'm.login_fail_cnt',
            'm.dt_login','m.dt_reg','m.dt_mod',
        ])->paginate($perPage)->withQueryString();
    }


    public function findMember(int $memNo): ?object
    {
        return DB::table('mem_info')->where('mem_no', $memNo)->first();
    }

    public function lockMemberForUpdate(int $memNo): ?object
    {
        return DB::table('mem_info')->where('mem_no', $memNo)->lockForUpdate()->first();
    }

    public function updateMember(int $memNo, array $data): bool
    {
        $data['dt_mod'] = $data['dt_mod'] ?? now()->format('Y-m-d H:i:s');
        return DB::table('mem_info')->where('mem_no', $memNo)->update($data) > 0;
    }

    public function getAuthRowsForMember(int $memNo): array
    {
        return DB::table('mem_auth')
            ->where('mem_no', $memNo)
            ->orderBy('auth_type')
            ->get()
            ->map(fn($r)=>(array)$r)
            ->all();
    }

    public function getAuthMapForMembers(array $memNos): array
    {
        if (empty($memNos)) return [];

        $rows = DB::table('mem_auth')
            ->whereIn('mem_no', $memNos)
            ->get(['mem_no','auth_type','auth_state','auth_date']);

        $map = [];
        foreach ($rows as $r) {
            $no = (int)$r->mem_no;
            $map[$no] ??= [];
            $map[$no][(string)$r->auth_type] = [
                'state' => (string)$r->auth_state,
                'date'  => (string)$r->auth_date,
            ];
        }
        return $map;
    }

    public function getAuthInfo(int $memNo): ?array
    {
        $row = DB::table('mem_auth_info')->where('mem_no', $memNo)->first();
        if (!$row) return null;

        $json = (string)($row->auth_info ?? '');
        $arr = json_decode($json, true);
        return is_array($arr) ? $arr : null;
    }

    public function getAuthLogs(int $memNo, int $limit = 30): array
    {
        return DB::table('mem_auth_log')
            ->where('mem_no', $memNo)
            ->orderByDesc('seq')
            ->limit($limit)
            ->get()
            ->map(fn($r)=>(array)$r)
            ->all();
    }

    public function getAddresses(int $memNo): array
    {
        return DB::table('mem_address')
            ->where('mem_no', $memNo)
            ->orderByDesc('seq')
            ->get()
            ->map(fn($r)=>(array)$r)
            ->all();
    }

    public function anonymizeAddresses(int $memNo): void
    {
        DB::table('mem_address')
            ->where('mem_no', $memNo)
            ->update([
                'shipping' => '',
                'zipNo' => '',
                'roadAddrPart1' => '',
                'jibunAddr' => '',
                'addrDetail' => '',
            ]);
    }
}
