<?php

namespace App\Services;

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

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

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

        $per = (int) ($params['per_page'] ?? $params['size'] ?? 20);
        $page = isset($params['page']) ? (int) $params['page'] : null;

        $q = TenantOptionGroup::where('tenant_id', $tenantId)->orderBy('group_key');

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

        $data = $q->paginate($per, ['*'], 'page', $page);

        return $data;
    }

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

        $v = Validator::make($params, [
            'group_key' => [
                'required', 'string', 'max:64', 'alpha_dash',
                Rule::unique('tenant_option_groups', 'group_key')
                    ->where(fn ($q) => $q->where('tenant_id', $tenantId)),
            ],
            'name' => ['required', 'string', 'max:100'],
            'description' => ['nullable', 'string', 'max:255'],
        ]);

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

        $data = $v->validated();
        $data['tenant_id'] = $tenantId;

        $item = TenantOptionGroup::create($data);

        return $item->toArray();
    }

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

        $item = TenantOptionGroup::where('tenant_id', $tenantId)->find($id);
        if (! $item) {
            return ['error' => '옵션 그룹을 찾을 수 없습니다.', 'code' => 404];
        }

        return $item->toArray();
    }

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

        $item = TenantOptionGroup::where('tenant_id', $tenantId)->find($id);
        if (! $item) {
            return ['error' => '옵션 그룹을 찾을 수 없습니다.', 'code' => 404];
        }

        $v = Validator::make($params, [
            'group_key' => [
                'sometimes', 'string', 'max:64', 'alpha_dash',
                Rule::unique('tenant_option_groups', 'group_key')
                    ->where(fn ($q) => $q->where('tenant_id', $tenantId))
                    ->ignore($item->id),
            ],
            'name' => ['sometimes', 'string', 'max:100'],
            'description' => ['nullable', 'string', 'max:255'],
        ]);

        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] 옵션 그룹 삭제
     * - 참조 무결성 검사:
     *   1) tenant_option_values에 값이 남아있으면 삭제 불가
     *   2) tenant_field_settings.option_group_id에서 참조 중이면 삭제 불가
     */
    public static function destroy(int $id)
    {
        $tenantId = self::tenantId();
        if (! $tenantId) {
            return ['error' => '활성 테넌트가 없습니다.', 'code' => 400];
        }
        if (! $id) {
            return ['error' => 'id가 올바르지 않습니다.', 'code' => 422];
        }

        $item = TenantOptionGroup::where('tenant_id', $tenantId)->find($id);
        if (! $item) {
            return ['error' => '옵션 그룹을 찾을 수 없습니다.', 'code' => 404];
        }

        // 1) 옵션 값 존재 여부
        $hasValues = TenantOptionValue::where('group_id', $item->id)->exists();
        if ($hasValues) {
            return ['error' => '해당 그룹에 옵션 값이 존재하여 삭제할 수 없습니다.', 'code' => 409];
        }

        // 2) 필드 설정에서 참조 여부
        $isReferenced = TenantFieldSetting::where('tenant_id', $tenantId)
            ->where('option_group_id', $item->id)
            ->exists();
        if ($isReferenced) {
            return ['error' => '필드 설정에서 참조 중인 그룹은 삭제할 수 없습니다.', 'code' => 409];
        }

        $item->delete();

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