<?php

namespace App\Services;

use App\Models\Tenants\SettingFieldDef;
use App\Models\Tenants\TenantFieldSetting;
use App\Models\Tenants\TenantUserProfile;
use Illuminate\Support\Facades\DB;

class TenantUserProfileService
{
    /** 활성 테넌트 ID */
    protected static function tenantId(): ?int
    {
        return app('tenant_id');
    }

    /** 효과값 필드(Enabled) 맵: field_key => [def, setting] */
    protected static function effectiveFieldMap(int $tenantId): array
    {
        $defs = SettingFieldDef::all()->keyBy('field_key');
        $settings = TenantFieldSetting::where('tenant_id', $tenantId)->get()->keyBy('field_key');

        $map = [];
        foreach ($defs as $key => $def) {
            $s = $settings->get($key);
            $enabled = $s ? (bool) $s->enabled : (bool) $def->is_core;
            if (! $enabled) {
                continue;
            }
            $map[$key] = ['def' => $def, 'setting' => $s];
        }

        return $map;
    }

    /**
     * [GET] 프로필 목록 (페이징)
     * params: per_page?, q?
     */
    public static function index(array $params = [])
    {
        $tenantId = self::tenantId();
        if (! $tenantId) {
            return ['error' => '활성 테넌트가 없습니다.', 'code' => 400];
        }

        $per = (int) ($params['per_page'] ?? $params['size'] ?? 20);
        $q = TenantUserProfile::where('tenant_id', $tenantId)
            ->with(['user:id,name,email']);

        if (! empty($params['q'])) {
            $kw = $params['q'];
            $q->where(function ($w) use ($kw) {
                $w->where('display_name', 'like', "%{$kw}%")
                    ->orWhere('json_extra->employee_no', 'like', "%{$kw}%");
            });
        }

        $page = isset($params['page']) ? (int) $params['page'] : null;
        $data = $q->orderByDesc('id')->paginate($per, ['*'], 'page', $page);

        return $data;
    }

    /**
     * [GET] 프로필 단건 조회
     */
    public static function show(int $userId)
    {
        $tenantId = self::tenantId();
        if (! $tenantId) {
            return ['error' => '활성 테넌트가 없습니다.', 'code' => 400];
        }
        if (! $userId) {
            return ['error' => 'userId가 올바르지 않습니다.', 'code' => 422];
        }

        $item = TenantUserProfile::where('tenant_id', $tenantId)
            ->where('user_id', $userId)
            ->with(['user:id,name,email'])
            ->first();

        if (! $item) {
            return ['error' => '프로필을 찾을 수 없습니다.', 'code' => 404];
        }

        return $item->toArray();
    }

    /**
     * [PATCH] 관리자 수정: enabled 필드만 write-back
     * - 입력 payload는 field_key: value 포맷(예: {"position":"manager","employee_no":"A-001"})
     */
    public static function update(int $userId, array $params = [])
    {
        $tenantId = self::tenantId();
        if (! $tenantId) {
            return ['error' => '활성 테넌트가 없습니다.', 'code' => 400];
        }
        if (! $userId) {
            return ['error' => 'userId가 올바르지 않습니다.', 'code' => 422];
        }

        // (선택) 간단 유효성: 최소 1개 키 존재
        if (empty($params) || ! is_array($params)) {
            return ['error' => '수정할 항목이 없습니다.', 'code' => 422];
        }

        $fields = self::effectiveFieldMap($tenantId);
        $profile = TenantUserProfile::firstOrCreate(['tenant_id' => $tenantId, 'user_id' => $userId]);

        try {
            DB::transaction(function () use ($fields, $profile, $params) {
                foreach ($fields as $key => $meta) {
                    if (! array_key_exists($key, $params)) {
                        continue;
                    } // 입력이 없으면 스킵

                    $def = $meta['def'];
                    $value = $params[$key];

                    switch ($def->storage_area) {
                        case 'tenant_profile':
                            if ($def->storage_key) {
                                $profile->{$def->storage_key} = $value;
                            }
                            break;

                        case 'tenant_profile_json':
                            $jsonKey = $def->storage_key ?: $key;
                            $extra = is_array($profile->json_extra) ? $profile->json_extra : (array) json_decode((string) $profile->json_extra, true);
                            $extra[$jsonKey] = $value;
                            $profile->json_extra = $extra;
                            break;

                        case 'users':
                            // 정책상 기본 비권장: 무시
                            // 필요 시 UsersService 등으로 화이트리스트 업데이트 구현
                            break;
                    }
                }
                $profile->save();
            });
        } catch (\Throwable $e) {
            return ['error' => '프로필 저장 중 오류가 발생했습니다.', 'code' => 500];
        }

        $fresh = TenantUserProfile::where('tenant_id', $tenantId)
            ->where('user_id', $userId)
            ->with(['user:id,name,email'])
            ->first();

        return $fresh ? $fresh->toArray() : null;
    }

    /**
     * [GET] 내 프로필 조회
     */
    public static function me(array $params = [])
    {
        $tenantId = self::tenantId();
        if (! $tenantId) {
            return ['error' => '활성 테넌트가 없습니다.', 'code' => 400];
        }
        $userId = auth()->id();
        if (! $userId) {
            return ['error' => '인증 정보가 없습니다.', 'code' => 401];
        }

        $item = TenantUserProfile::where('tenant_id', $tenantId)
            ->where('user_id', $userId)
            ->with(['user:id,name,email'])
            ->first();

        // 없으면 null 반환(스펙에 따라 404로 바꾸려면 위와 동일 처리)
        return $item ? $item->toArray() : null;
    }

    /**
     * [PATCH] 내 프로필 수정
     * - 고정 필드(profile_photo_path, display_name)는 직접 처리
     * - 동적 필드(enabled 필드)는 기존 update 로직으로 처리
     */
    public static function updateMe(array $params = [])
    {
        $tenantId = self::tenantId();
        if (! $tenantId) {
            return ['error' => '활성 테넌트가 없습니다.', 'code' => 400];
        }
        $userId = auth()->id();
        if (! $userId) {
            return ['error' => '인증 정보가 없습니다.', 'code' => 401];
        }

        // 고정 필드 추출 (동적 필드 처리 전에 직접 저장)
        $fixedFields = ['profile_photo_path', 'display_name'];
        $fixedData = [];
        foreach ($fixedFields as $field) {
            if (array_key_exists($field, $params)) {
                $fixedData[$field] = $params[$field];
                unset($params[$field]);
            }
        }

        // 고정 필드가 있으면 직접 업데이트
        if (! empty($fixedData)) {
            $profile = TenantUserProfile::firstOrCreate([
                'tenant_id' => $tenantId,
                'user_id' => $userId,
            ]);
            $profile->fill($fixedData);
            $profile->save();
        }

        // 동적 필드가 남아있으면 기존 로직으로 처리
        if (! empty($params)) {
            return self::update($userId, $params);
        }

        // 고정 필드만 있었으면 새로고침된 프로필 반환
        $fresh = TenantUserProfile::where('tenant_id', $tenantId)
            ->where('user_id', $userId)
            ->with(['user:id,name,email'])
            ->first();

        return $fresh ? $fresh->toArray() : null;
    }
}
