<?php

namespace App\Services;

use App\Models\Tenants\TenantOptionGroup;
use App\Models\Tenants\TenantOptionValue;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

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

    /** 테넌트 소유 그룹 로드 (없으면 null) */
    protected static function loadGroup(int $tenantId, int $groupId): ?TenantOptionGroup
    {
        return TenantOptionGroup::where('tenant_id', $tenantId)->find($groupId);
    }

    /**
     * [GET] 옵션 값 목록
     * params: active_only?(bool)
     */
    public static function index(int $groupId, array $params = [])
    {
        $tenantId = self::tenantId();
        if (! $tenantId) {
            return ['error' => '활성 테넌트가 없습니다.', 'code' => 400];
        }

        $group = self::loadGroup($tenantId, $groupId);
        if (! $group) {
            return ['error' => '옵션 그룹을 찾을 수 없습니다.', 'code' => 404];
        }

        $q = TenantOptionValue::where('group_id', $group->id)
            ->orderBy('sort_order')
            ->orderBy('value_label');

        if (! empty($params['active_only'])) {
            $q->where('is_active', 1);
        }

        $list = $q->get();

        return $list;
    }

    /**
     * [POST] 옵션 값 생성
     */
    public static function store(int $groupId, array $params = [])
    {
        $tenantId = self::tenantId();
        if (! $tenantId) {
            return ['error' => '활성 테넌트가 없습니다.', 'code' => 400];
        }

        $group = self::loadGroup($tenantId, $groupId);
        if (! $group) {
            return ['error' => '옵션 그룹을 찾을 수 없습니다.', 'code' => 404];
        }

        $v = Validator::make($params, [
            'value_key' => [
                'required', 'string', 'max:64', 'alpha_dash',
                Rule::unique('tenant_option_values', 'value_key')
                    ->where(fn ($q) => $q->where('group_id', $group->id)),
            ],
            'value_label' => ['required', 'string', 'max:100'],
            'sort_order' => ['nullable', 'integer'],
            'is_active' => ['nullable', 'boolean'],
        ]);

        if ($v->fails()) {
            return ['error' => $v->errors()->first(), 'code' => 422];
        }

        $data = $v->validated();
        $data['group_id'] = $group->id;
        $item = TenantOptionValue::create($data);

        return $item->toArray();
    }

    /**
     * [GET] 옵션 값 단건 조회
     */
    public static function show(int $groupId, int $id)
    {
        $tenantId = self::tenantId();
        if (! $tenantId) {
            return ['error' => '활성 테넌트가 없습니다.', 'code' => 400];
        }

        $group = self::loadGroup($tenantId, $groupId);
        if (! $group) {
            return ['error' => '옵션 그룹을 찾을 수 없습니다.', 'code' => 404];
        }

        $item = TenantOptionValue::where('group_id', $group->id)->find($id);
        if (! $item) {
            return ['error' => '옵션 값을 찾을 수 없습니다.', 'code' => 404];
        }

        return $item->toArray();
    }

    /**
     * [PATCH] 옵션 값 수정
     */
    public static function update(int $groupId, int $id, array $params = [])
    {
        $tenantId = self::tenantId();
        if (! $tenantId) {
            return ['error' => '활성 테넌트가 없습니다.', 'code' => 400];
        }

        $group = self::loadGroup($tenantId, $groupId);
        if (! $group) {
            return ['error' => '옵션 그룹을 찾을 수 없습니다.', 'code' => 404];
        }

        $item = TenantOptionValue::where('group_id', $group->id)->find($id);
        if (! $item) {
            return ['error' => '옵션 값을 찾을 수 없습니다.', 'code' => 404];
        }

        $v = Validator::make($params, [
            'value_key' => [
                'sometimes', 'string', 'max:64', 'alpha_dash',
                Rule::unique('tenant_option_values', 'value_key')
                    ->where(fn ($q) => $q->where('group_id', $group->id))
                    ->ignore($item->id),
            ],
            'value_label' => ['sometimes', 'string', 'max:100'],
            'sort_order' => ['nullable', 'integer'],
            'is_active' => ['nullable', 'boolean'],
        ]);

        if ($v->fails()) {
            return ['error' => $v->errors()->first(), 'code' => 422];
        }

        $data = $v->validated();
        if (empty($data)) {
            return ['error' => '수정할 항목이 없습니다.', 'code' => 422];
        }

        $item->fill($data)->save();

        return $item->toArray();
    }

    /**
     * [DELETE] 옵션 값 삭제
     * - TODO: 실제 프로필/필드설정에서 value_key 참조 여부 체크가 필요하면 여기서 차단
     */
    public static function destroy(int $groupId, int $id)
    {
        $tenantId = self::tenantId();
        if (! $tenantId) {
            return ['error' => '활성 테넌트가 없습니다.', 'code' => 400];
        }

        $group = self::loadGroup($tenantId, $groupId);
        if (! $group) {
            return ['error' => '옵션 그룹을 찾을 수 없습니다.', 'code' => 404];
        }

        $item = TenantOptionValue::where('group_id', $group->id)->find($id);
        if (! $item) {
            return ['error' => '옵션 값을 찾을 수 없습니다.', 'code' => 404];
        }

        // TODO: 참조 무결성 검사(필요 시 구현)
        $item->delete();

        return ['deleted' => true];
    }

    /**
     * [PATCH] 정렬 순서 일괄 변경
     * params: items: [{id, sort_order}, ...]
     */
    public static function reorder(int $groupId, array $params = [])
    {
        $tenantId = self::tenantId();
        if (! $tenantId) {
            return ['error' => '활성 테넌트가 없습니다.', 'code' => 400];
        }

        $group = self::loadGroup($tenantId, $groupId);
        if (! $group) {
            return ['error' => '옵션 그룹을 찾을 수 없습니다.', 'code' => 404];
        }

        $v = Validator::make($params, [
            'items' => ['required', 'array', 'min:1'],
            'items.*.id' => ['required', 'integer'],
            'items.*.sort_order' => ['required', 'integer'],
        ]);

        if ($v->fails()) {
            return ['error' => $v->errors()->first(), 'code' => 422];
        }

        $rows = $v->validated()['items'];

        try {
            DB::transaction(function () use ($group, $rows) {
                foreach ($rows as $r) {
                    TenantOptionValue::where('group_id', $group->id)
                        ->where('id', $r['id'])
                        ->update(['sort_order' => (int) $r['sort_order']]);
                }
            });
        } catch (\Throwable $e) {
            return ['error' => '정렬 순서 저장 중 오류가 발생했습니다.', 'code' => 500];
        }

        return ['reordered' => true];
    }
}
