<?php

namespace App\Helpers;

use App\Models\Products\CommonCode;
use Illuminate\Support\Facades\Cache;

/**
 * 품목 유형(item_type) 관련 헬퍼 클래스
 *
 * - 품목 유형 코드(FG/PT/SM/RM/CS) → 테이블(products/materials) 매핑
 * - 테넌트별 캐시 적용
 */
class ItemTypeHelper
{
    /**
     * 캐시 TTL (초)
     */
    private const CACHE_TTL = 3600; // 1시간

    /**
     * 캐시 키 프리픽스
     */
    private const CACHE_PREFIX = 'item_types:tenant:';

    /**
     * 테넌트별 품목 유형 목록 조회 (캐시 적용)
     *
     * @return array<string, array{code: string, name: string, source_table: string}>
     */
    public static function getTypesByTenant(int $tenantId): array
    {
        $cacheKey = self::CACHE_PREFIX.$tenantId;

        return Cache::remember($cacheKey, self::CACHE_TTL, function () use ($tenantId) {
            $codes = CommonCode::query()
                ->where(function ($query) use ($tenantId) {
                    $query->where('tenant_id', $tenantId)
                        ->orWhereNull('tenant_id');
                })
                ->where('code_group', 'item_type')
                ->where('is_active', true)
                ->orderBy('sort_order')
                ->get(['code', 'name', 'attributes']);

            $result = [];
            foreach ($codes as $code) {
                $attributes = is_array($code->attributes) ? $code->attributes : json_decode($code->attributes, true) ?? [];
                $result[$code->code] = [
                    'code' => $code->code,
                    'name' => $code->name,
                    'source_table' => $attributes['source_table'] ?? 'products',
                ];
            }

            return $result;
        });
    }

    /**
     * 품목 유형이 Material인지 확인
     *
     * @param  string  $itemType  품목 유형 코드 (FG/PT/SM/RM/CS)
     * @param  int  $tenantId  테넌트 ID
     */
    public static function isMaterial(string $itemType, int $tenantId): bool
    {
        return self::getSourceTable($itemType, $tenantId) === 'materials';
    }

    /**
     * 품목 유형이 Product인지 확인
     *
     * @param  string  $itemType  품목 유형 코드 (FG/PT/SM/RM/CS)
     * @param  int  $tenantId  테넌트 ID
     */
    public static function isProduct(string $itemType, int $tenantId): bool
    {
        return self::getSourceTable($itemType, $tenantId) === 'products';
    }

    /**
     * 품목 유형에 해당하는 소스 테이블 반환
     *
     * @param  string  $itemType  품목 유형 코드 (FG/PT/SM/RM/CS)
     * @param  int  $tenantId  테넌트 ID
     * @return string 'products' | 'materials'
     */
    public static function getSourceTable(string $itemType, int $tenantId): string
    {
        $itemType = strtoupper($itemType);
        $types = self::getTypesByTenant($tenantId);

        if (isset($types[$itemType])) {
            return $types[$itemType]['source_table'];
        }

        // 기본 매핑 (캐시 미스 또는 알 수 없는 타입)
        return self::getDefaultSourceTable($itemType);
    }

    /**
     * 기본 소스 테이블 매핑 (DB 조회 없이)
     *
     * @param  string  $itemType  품목 유형 코드
     * @return string 'products' | 'materials'
     */
    public static function getDefaultSourceTable(string $itemType): string
    {
        $itemType = strtoupper($itemType);

        // Material 타입: SM, RM, CS
        if (in_array($itemType, ['SM', 'RM', 'CS'])) {
            return 'materials';
        }

        // Product 타입: FG, PT (기본값)
        return 'products';
    }

    /**
     * 캐시 무효화
     */
    public static function clearCache(int $tenantId): void
    {
        $cacheKey = self::CACHE_PREFIX.$tenantId;
        Cache::forget($cacheKey);
    }

    /**
     * 전체 캐시 무효화 (모든 테넌트)
     */
    public static function clearAllCache(): void
    {
        // 패턴 기반 삭제는 캐시 드라이버에 따라 지원 여부가 다름
        // 간단히 태그 기반 캐시나 개별 삭제를 권장
        // 여기서는 특정 테넌트 캐시만 삭제하는 것을 권장
    }

    /**
     * 유효한 품목 유형인지 확인
     *
     * @param  string  $itemType  품목 유형 코드
     * @param  int  $tenantId  테넌트 ID
     */
    public static function isValidType(string $itemType, int $tenantId): bool
    {
        $itemType = strtoupper($itemType);
        $types = self::getTypesByTenant($tenantId);

        return isset($types[$itemType]);
    }

    /**
     * 모든 유효한 품목 유형 코드 목록 반환
     *
     * @return array<string>
     */
    public static function getValidTypeCodes(int $tenantId): array
    {
        $types = self::getTypesByTenant($tenantId);

        return array_keys($types);
    }
}
