<?php

namespace App\Services;

use App\Models\Archives\ArchivedRecord;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

class ArchivedRecordService
{
    /**
     * 아카이브 레코드 목록 조회 (batch_id로 그룹핑, 페이지네이션)
     * batch_id가 NULL인 기존 데이터는 각각 개별 batch로 취급
     *
     * NOTE: GROUP BY + paginate() 조합 시 total count가 잘못 계산되는 문제 해결
     *       서브쿼리로 GROUP BY 결과를 감싼 후 외부에서 paginate() 실행
     */
    public function getArchivedRecordsBatched(array $filters = [], int $perPage = 15): LengthAwarePaginator
    {
        // 1. 서브쿼리: batch_id별 그룹핑
        $subQuery = ArchivedRecord::query()
            ->select([
                DB::raw("COALESCE(batch_id, CONCAT('legacy_', id)) as batch_id"),
                DB::raw("COALESCE(batch_description, CONCAT(record_type, ' 삭제 (ID: ', original_id, ')')) as batch_description"),
                DB::raw('MIN(id) as id'),
                DB::raw('MIN(tenant_id) as tenant_id'),
                DB::raw('GROUP_CONCAT(DISTINCT record_type) as record_types'),
                DB::raw('COUNT(*) as record_count'),
                DB::raw('MIN(deleted_by) as deleted_by'),
                DB::raw('MIN(deleted_at) as deleted_at'),
                // 대상 정보 추출 (테넌트명, 사용자명 등)
                DB::raw("MAX(JSON_UNQUOTE(JSON_EXTRACT(main_data, '$.company_name'))) as target_company_name"),
                DB::raw("MAX(JSON_UNQUOTE(JSON_EXTRACT(main_data, '$.name'))) as target_name"),
                DB::raw("MAX(JSON_UNQUOTE(JSON_EXTRACT(main_data, '$.email'))) as target_email"),
                DB::raw("MAX(JSON_UNQUOTE(JSON_EXTRACT(main_data, '$.code'))) as target_code"),
            ]);

        // 테넌트 필터링 (서브쿼리에서 적용)
        if (! empty($filters['tenant_id'])) {
            $subQuery->where('tenant_id', $filters['tenant_id']);
        }

        $subQuery->groupBy(
            DB::raw("COALESCE(batch_id, CONCAT('legacy_', id))"),
            DB::raw("COALESCE(batch_description, CONCAT(record_type, ' 삭제 (ID: ', original_id, ')'))")
        );

        // 2. 외부 쿼리: 서브쿼리를 감싸서 정확한 count 계산
        $query = DB::table(DB::raw("({$subQuery->toSql()}) as grouped"))
            ->mergeBindings($subQuery->getQuery())
            ->select('*');

        // 레코드 타입 필터
        if (! empty($filters['record_type'])) {
            $query->where('record_types', 'like', "%{$filters['record_type']}%");
        }

        // 삭제자 필터
        if (! empty($filters['deleted_by'])) {
            $query->where('deleted_by', $filters['deleted_by']);
        }

        // 검색
        if (! empty($filters['search'])) {
            $query->where('batch_description', 'like', "%{$filters['search']}%");
        }

        // 정렬 (기본: 삭제일시 내림차순)
        $sortBy = $filters['sort_by'] ?? 'deleted_at';
        $sortDirection = $filters['sort_direction'] ?? 'desc';
        $query->orderBy($sortBy, $sortDirection);

        // NOTE: DB::table() 사용 시 request의 page 파라미터를 자동으로 읽지 못함
        //       filters에서 page를 명시적으로 전달
        $page = $filters['page'] ?? null;

        return $query->paginate($perPage, ['*'], 'page', $page);
    }

    /**
     * 특정 batch의 모든 레코드 조회
     * legacy_ 접두사가 붙은 경우 단일 레코드 ID로 조회
     */
    public function getRecordsByBatchId(string $batchId): Collection
    {
        // legacy_ 접두사가 붙은 경우 (기존 데이터)
        if (str_starts_with($batchId, 'legacy_')) {
            $id = (int) str_replace('legacy_', '', $batchId);

            return ArchivedRecord::with(['deletedByUser', 'relations'])
                ->where('id', $id)
                ->get();
        }

        return ArchivedRecord::with(['deletedByUser', 'relations'])
            ->where('batch_id', $batchId)
            ->orderBy('id')
            ->get();
    }

    /**
     * 특정 아카이브 레코드 조회
     */
    public function getArchivedRecordById(int $id): ?ArchivedRecord
    {
        return ArchivedRecord::with(['deletedByUser', 'relations'])
            ->find($id);
    }

    /**
     * batch_id로 첫 번째 레코드 조회 (상세 페이지 진입용)
     */
    public function getFirstRecordByBatchId(string $batchId): ?ArchivedRecord
    {
        return ArchivedRecord::with(['deletedByUser', 'relations'])
            ->where('batch_id', $batchId)
            ->orderBy('id')
            ->first();
    }

    /**
     * 삭제자 목록 조회 (필터용)
     */
    public function getDeletedByUsers(): array
    {
        return ArchivedRecord::query()
            ->whereNotNull('deleted_by')
            ->with('deletedByUser:id,name')
            ->get()
            ->pluck('deletedByUser')
            ->filter()
            ->unique('id')
            ->values()
            ->toArray();
    }

    /**
     * 아카이브 통계
     */
    public function getStats(): array
    {
        return [
            'total_batches' => ArchivedRecord::distinct('batch_id')->count('batch_id'),
            'total_records' => ArchivedRecord::count(),
            'tenants' => ArchivedRecord::tenant()->count(),
            'users' => ArchivedRecord::user()->count(),
        ];
    }
}
