<?php

namespace App\Services;

use App\Models\Commons\Category;
use App\Models\Commons\CategoryField;
use Illuminate\Support\Facades\DB;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

class CategoryFieldService extends Service
{
    public function index(int $categoryId, array $params)
    {
        $tenantId = $this->tenantId();

        $size = (int) ($params['size'] ?? 20);
        $sort = $params['sort'] ?? 'sort_order';
        $order = strtolower($params['order'] ?? 'asc') === 'desc' ? 'desc' : 'asc';

        return CategoryField::query()
            ->where('tenant_id', $tenantId)
            ->where('category_id', $categoryId)
            ->orderBy($sort, $order)
            ->paginate($size);
    }

    public function store(int $categoryId, array $data)
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        $this->assertCategoryExists($tenantId, $categoryId);

        // FormRequest에서 이미 검증됨
        $payload = $data;

        // 카테고리 내 field_key 유니크 검증
        $exists = CategoryField::query()
            ->where('tenant_id', $tenantId)
            ->where('category_id', $categoryId)
            ->where('field_key', $payload['field_key'])
            ->exists();
        if ($exists) {
            throw new BadRequestHttpException(__('error.duplicate_key'));
        }

        $payload['tenant_id'] = $tenantId;
        $payload['category_id'] = $categoryId;
        $payload['is_required'] = $payload['is_required'] ?? false;
        $payload['sort_order'] = $payload['sort_order'] ?? 0;
        $payload['created_by'] = $userId;

        return CategoryField::create($payload);
    }

    public function show(int $fieldId)
    {
        $tenantId = $this->tenantId();

        $field = CategoryField::query()
            ->where('tenant_id', $tenantId)
            ->find($fieldId);

        if (! $field) {
            throw new BadRequestHttpException(__('error.not_found'));
        }

        return $field;
    }

    public function update(int $fieldId, array $data)
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        $field = CategoryField::query()
            ->where('tenant_id', $tenantId)
            ->find($fieldId);

        if (! $field) {
            throw new BadRequestHttpException(__('error.not_found'));
        }

        // FormRequest에서 이미 검증됨
        $payload = $data;

        if (isset($payload['field_key']) && $payload['field_key'] !== $field->field_key) {
            $dup = CategoryField::query()
                ->where('tenant_id', $tenantId)
                ->where('category_id', $field->category_id)
                ->where('field_key', $payload['field_key'])
                ->exists();
            if ($dup) {
                throw new BadRequestHttpException(__('error.duplicate_key'));
            }
        }

        $payload['updated_by'] = $userId;
        $field->update($payload);

        return $field->refresh();
    }

    public function destroy(int $fieldId): void
    {
        $tenantId = $this->tenantId();
        $field = CategoryField::query()
            ->where('tenant_id', $tenantId)
            ->find($fieldId);

        if (! $field) {
            throw new BadRequestHttpException(__('error.not_found'));
        }
        $field->delete();
    }

    public function reorder(int $categoryId, array $items): void
    {
        $tenantId = $this->tenantId();
        $this->assertCategoryExists($tenantId, $categoryId);

        $rows = $items['items'] ?? $items; // 둘 다 허용
        if (! is_array($rows)) {
            throw new BadRequestHttpException(__('error.invalid_payload'));
        }

        DB::transaction(function () use ($tenantId, $categoryId, $rows) {
            foreach ($rows as $row) {
                if (! isset($row['id'], $row['sort_order'])) {
                    continue;
                }
                CategoryField::query()
                    ->where('tenant_id', $tenantId)
                    ->where('category_id', $categoryId)
                    ->where('id', $row['id'])
                    ->update(['sort_order' => (int) $row['sort_order']]);
            }
        });
    }

    public function bulkUpsert(int $categoryId, array $items): array
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();
        $this->assertCategoryExists($tenantId, $categoryId);

        if (! is_array($items) || empty($items)) {
            throw new BadRequestHttpException(__('error.empty_items'));
        }

        $result = ['created' => 0, 'updated' => 0];

        DB::transaction(function () use ($tenantId, $userId, $categoryId, $items, &$result) {
            foreach ($items as $payload) {
                // 기본적인 검증 (FormRequest가 배열 내부까지는 검증 못함)
                if (! isset($payload['field_name'], $payload['field_type'])) {
                    throw new BadRequestHttpException(__('error.invalid_payload'));
                }

                if (! empty($payload['id'])) {
                    $model = CategoryField::query()
                        ->where('tenant_id', $tenantId)
                        ->where('category_id', $categoryId)
                        ->find($payload['id']);
                    if (! $model) {
                        throw new BadRequestHttpException(__('error.not_found'));
                    }

                    // field_key 변경 유니크 검사
                    if (isset($payload['field_key']) && $payload['field_key'] !== $model->field_key) {
                        $dup = CategoryField::query()
                            ->where('tenant_id', $tenantId)
                            ->where('category_id', $categoryId)
                            ->where('field_key', $payload['field_key'])
                            ->exists();
                        if ($dup) {
                            throw new BadRequestHttpException(__('error.duplicate_key'));
                        }
                    }

                    $payload['updated_by'] = $userId;
                    $model->update($payload);
                    $result['updated']++;
                } else {
                    // 신규 생성
                    if (empty($payload['field_key'])) {
                        throw new BadRequestHttpException(__('error.required', ['attr' => 'field_key']));
                    }
                    $dup = CategoryField::query()
                        ->where('tenant_id', $tenantId)
                        ->where('category_id', $categoryId)
                        ->where('field_key', $payload['field_key'])
                        ->exists();
                    if ($dup) {
                        throw new BadRequestHttpException(__('error.duplicate_key'));
                    }

                    $payload['tenant_id'] = $tenantId;
                    $payload['category_id'] = $categoryId;
                    $payload['is_required'] = $payload['is_required'] ?? false;
                    $payload['sort_order'] = $payload['sort_order'] ?? 0;
                    $payload['created_by'] = $userId;

                    CategoryField::create($payload);
                    $result['created']++;
                }
            }
        });

        return $result;
    }

    private function assertCategoryExists(int $tenantId, int $categoryId): void
    {
        $exists = Category::query()
            ->where('tenant_id', $tenantId)
            ->where('id', $categoryId)
            ->exists();
        if (! $exists) {
            throw new BadRequestHttpException(__('error.category_not_found'));
        }
    }
}
