<?php

namespace App\Services;

use App\Models\Tenants\TenantStatField;
use Illuminate\Support\Facades\DB;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

class TenantStatFieldService extends Service
{
    public function index(array $params)
    {
        $tenantId = $this->tenantId();

        $size = (int) ($params['size'] ?? 20);
        $targetTable = $params['target_table'] ?? null;
        $isCritical = $params['is_critical'] ?? null;
        $aggregationType = $params['aggregation_type'] ?? null;

        $query = TenantStatField::query()
            ->where('tenant_id', $tenantId);

        // 필터: 대상 테이블
        if ($targetTable) {
            $query->forTable($targetTable);
        }

        // 필터: 중요 필드만
        if ($isCritical !== null && $isCritical !== '') {
            $query->critical();
        }

        // 필터: 특정 집계 함수 포함
        if ($aggregationType) {
            $query->withAggregation($aggregationType);
        }

        // 정렬: display_order, field_name
        $query->ordered();

        return $query->paginate($size);
    }

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

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

        // tenant_id + target_table + field_key 유니크 검증
        $exists = TenantStatField::query()
            ->where('tenant_id', $tenantId)
            ->where('target_table', $payload['target_table'])
            ->where('field_key', $payload['field_key'])
            ->exists();
        if ($exists) {
            throw new BadRequestHttpException(__('error.duplicate_key'));
        }

        $payload['tenant_id'] = $tenantId;
        $payload['is_critical'] = $payload['is_critical'] ?? false;
        $payload['display_order'] = $payload['display_order'] ?? 0;
        $payload['created_by'] = $userId;

        return TenantStatField::create($payload);
    }

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

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

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

        return $field;
    }

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

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

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

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

        // target_table 또는 field_key 변경 시 유니크 검증
        $targetTableChanged = isset($payload['target_table']) && $payload['target_table'] !== $field->target_table;
        $fieldKeyChanged = isset($payload['field_key']) && $payload['field_key'] !== $field->field_key;

        if ($targetTableChanged || $fieldKeyChanged) {
            $newTargetTable = $payload['target_table'] ?? $field->target_table;
            $newFieldKey = $payload['field_key'] ?? $field->field_key;

            $dup = TenantStatField::query()
                ->where('tenant_id', $tenantId)
                ->where('target_table', $newTargetTable)
                ->where('field_key', $newFieldKey)
                ->where('id', '!=', $id)
                ->exists();
            if ($dup) {
                throw new BadRequestHttpException(__('error.duplicate_key'));
            }
        }

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

        return $field->refresh();
    }

    public function destroy(int $id): void
    {
        $tenantId = $this->tenantId();

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

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

        $field->delete();
    }

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

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

        DB::transaction(function () use ($tenantId, $rows) {
            foreach ($rows as $row) {
                if (! isset($row['id'], $row['display_order'])) {
                    continue;
                }

                TenantStatField::query()
                    ->where('tenant_id', $tenantId)
                    ->where('id', $row['id'])
                    ->update(['display_order' => (int) $row['display_order']]);
            }
        });
    }

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

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

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

        DB::transaction(function () use ($tenantId, $userId, $items, &$result) {
            foreach ($items as $payload) {
                // 기본 검증
                if (! isset($payload['target_table'], $payload['field_key'], $payload['field_name'], $payload['field_type'])) {
                    throw new BadRequestHttpException(__('error.invalid_payload'));
                }

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

                    // target_table 또는 field_key 변경 시 유니크 검증
                    $targetTableChanged = isset($payload['target_table']) && $payload['target_table'] !== $model->target_table;
                    $fieldKeyChanged = isset($payload['field_key']) && $payload['field_key'] !== $model->field_key;

                    if ($targetTableChanged || $fieldKeyChanged) {
                        $newTargetTable = $payload['target_table'] ?? $model->target_table;
                        $newFieldKey = $payload['field_key'] ?? $model->field_key;

                        $dup = TenantStatField::query()
                            ->where('tenant_id', $tenantId)
                            ->where('target_table', $newTargetTable)
                            ->where('field_key', $newFieldKey)
                            ->where('id', '!=', $payload['id'])
                            ->exists();
                        if ($dup) {
                            throw new BadRequestHttpException(__('error.duplicate_key'));
                        }
                    }

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

                    $payload['tenant_id'] = $tenantId;
                    $payload['is_critical'] = $payload['is_critical'] ?? false;
                    $payload['display_order'] = $payload['display_order'] ?? 0;
                    $payload['created_by'] = $userId;

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

        return $result;
    }
}
