<?php

namespace App\Repositories\Admin\Cs;

use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\LengthAwarePaginator as Paginator;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

final class AdminQnaRepository
{
    public function table(int $year): string
    {
        return "counseling_one_on_one_{$year}";
    }

    public function hasYearTable(int $year): bool
    {
        return Schema::hasTable($this->table($year));
    }

    public function paginate(int $year, array $filters, int $perPage): LengthAwarePaginator
    {
        if (!$this->hasYearTable($year)) {
            return new Paginator([], 0, $perPage, 1, [
                'path'  => request()->url(),
                'query' => request()->query(),
            ]);
        }

        $t = $this->table($year);

        $q = DB::table("{$t} as q")
            ->select([
                'q.seq','q.state','q.enquiry_code','q.enquiry_title','q.member_num','q.regdate','q.answer_admin_num',
                'q.return_type','q.completion_date',
            ])
            ->when(($filters['enquiry_code'] ?? '') !== '', fn($w) => $w->where('q.enquiry_code', $filters['enquiry_code']))
            ->when(($filters['state'] ?? '') !== '', fn($w) => $w->where('q.state', $filters['state']))
            ->when(($filters['my_work'] ?? '') === '1' && (int)($filters['admin_id'] ?? 0) > 0,
                fn($w) => $w->where('q.answer_admin_num', (int)$filters['admin_id'])
            )
            ->when(($filters['date_from'] ?? '') !== '', fn($w) => $w->where('q.regdate', '>=', $filters['date_from'].' 00:00:00'))
            ->when(($filters['date_to'] ?? '') !== '', fn($w) => $w->where('q.regdate', '<=', $filters['date_to'].' 23:59:59'))
            ->orderByDesc('q.seq');

        // 검색
        $qText = trim((string)($filters['q'] ?? ''));
        $qType = (string)($filters['q_type'] ?? 'title');

        if ($qText !== '') {
            if ($qType === 'title') {
                $q->where('q.enquiry_title', 'like', "%{$qText}%");
            } elseif ($qType === 'member_no' && ctype_digit($qText)) {
                $q->where('q.member_num', (int)$qText);
            } elseif ($qType === 'member_email') {
                $memNo = $this->findMemberNoByEmail($qText);
                $q->where('q.member_num', $memNo > 0 ? $memNo : -1);
            } elseif ($qType === 'admin_email') {
                $adminId = $this->findAdminIdByEmail($qText);
                $q->where('q.answer_admin_num', $adminId > 0 ? $adminId : -1);
            }
        }

        return $q->paginate($perPage)->withQueryString();
    }

    public function findOrFail(int $year, int $seq): object
    {
        if (!$this->hasYearTable($year)) abort(404);

        $t = $this->table($year);

        $row = DB::table($t)->where('seq', $seq)->first();
        if (!$row) abort(404);
        return $row;
    }

    public function lockForUpdate(int $year, int $seq, array $cols = ['*']): object
    {
        if (!$this->hasYearTable($year)) abort(404);
        $t = $this->table($year);

        $row = DB::table($t)->select($cols)->where('seq', $seq)->lockForUpdate()->first();
        if (!$row) abort(404);
        return $row;
    }

    public function update(int $year, int $seq, array $data): int
    {
        $t = $this->table($year);
        return DB::table($t)->where('seq', $seq)->update($data);
    }

    public function getEnquiryCodes(): array
    {
        return DB::table('counseling_code')
            ->where('enquiry_type', 'e')
            ->orderBy('enquiry_code', 'asc')
            ->get(['enquiry_code','enquiry_title'])
            ->map(fn($r) => ['code'=>(string)$r->enquiry_code, 'title'=>(string)$r->enquiry_title])
            ->all();
    }

    public function getDeferCodes(): array
    {
        return DB::table('counseling_code')
            ->where('enquiry_type', 'd')
            ->orderBy('enquiry_code', 'asc')
            ->get(['enquiry_code','enquiry_title'])
            ->map(fn($r) => ['code'=>(string)$r->enquiry_code, 'title'=>(string)$r->enquiry_title])
            ->all();
    }

    public function findMemberNoByEmail(string $email): int
    {
        $row = DB::table('mem_info')->where('email', $email)->first(['mem_no']);
        return (int)($row->mem_no ?? 0);
    }

    public function findAdminIdByEmail(string $email): int
    {
        $row = DB::table('admin_users')->where('email', $email)->first(['id']);
        return (int)($row->id ?? 0);
    }

    public function getMemberInfo(int $memNo): ?object
    {
        return DB::table('mem_info')->where('mem_no', $memNo)->first(['mem_no','email','name','cell_phone']);
    }

    public function getRecentOrders(int $memNo, int $limit = 10): array
    {
        // 테이블/컬럼은 네 DB에 맞춰 조정 가능 (CI3 pin_order 기반)
        if (!Schema::hasTable('pin_order')) return [];

        return DB::table('pin_order')
            ->where('mem_no', $memNo)
            ->whereIn('stat_pay', ['p','w','c'])
            ->orderByDesc('seq')
            ->limit($limit)
            ->get()
            ->all();
    }

    public function getAdminsByIds(array $ids): array
    {
        $ids = array_values(array_unique(array_filter(array_map('intval', $ids))));
        if (!$ids) return [];

        return DB::table('admin_users')
            ->whereIn('id', $ids)
            ->get(['id','email','name'])
            ->keyBy('id')
            ->map(fn($r) => ['id'=>(int)$r->id,'email'=>(string)$r->email,'name'=>(string)$r->name])
            ->all();
    }
}
