<?php

namespace App\Services\ModelSet;

use App\Models\Commons\Category;
use App\Models\Commons\CategoryField;
use App\Models\Design\BomTemplate;
use App\Models\Design\Model;
use App\Models\Design\ModelVersion;
use App\Models\Products\Product;
use App\Services\Calculation\CalculationEngine;
use App\Services\Service;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

class ModelSetService extends Service
{
    protected CalculationEngine $calculationEngine;

    public function __construct(CalculationEngine $calculationEngine)
    {
        $this->calculationEngine = $calculationEngine;
    }

    /**
     * 모델셋 목록 조회 (카테고리 기반)
     */
    public function getModelSets(array $filters = []): Collection
    {
        $query = Category::with(['fields', 'children'])
            ->where('tenant_id', $this->tenantId())
            ->where('code_group', 'estimate')
            ->where('level', '>=', 2); // 루트 카테고리 제외

        if (! empty($filters['category_type'])) {
            $query->where('code', $filters['category_type']);
        }

        if (! empty($filters['is_active'])) {
            $query->where('is_active', $filters['is_active']);
        }

        return $query->orderBy('sort_order')->get();
    }

    /**
     * 모델셋 상세 조회
     */
    public function getModelSetDetail($categoryId): array
    {
        $category = Category::with(['fields', 'parent', 'children'])
            ->where('tenant_id', $this->tenantId())
            ->findOrFail($categoryId);

        // 해당 카테고리의 제품들
        $products = Product::where('tenant_id', $this->tenantId())
            ->where('category_id', $categoryId)
            ->with(['components'])
            ->get();

        // 해당 카테고리의 모델 및 BOM 템플릿들
        $models = $this->getRelatedModels($categoryId);

        return [
            'category' => $category,
            'products' => $products,
            'models' => $models,
            'field_schema' => $this->generateFieldSchema($category->fields),
        ];
    }

    /**
     * 새로운 모델셋 생성
     */
    public function createModelSet(array $data): array
    {
        return DB::transaction(function () use ($data) {
            // 1. 카테고리 생성
            $category = Category::create([
                'tenant_id' => $this->tenantId(),
                'parent_id' => $data['parent_id'] ?? null,
                'code_group' => 'estimate',
                'code' => $data['code'],
                'name' => $data['name'],
                'description' => $data['description'] ?? '',
                'level' => $data['level'] ?? 2,
                'sort_order' => $data['sort_order'] ?? 999,
                'profile_code' => $data['profile_code'] ?? 'custom_category',
                'is_active' => $data['is_active'] ?? true,
                'created_by' => $this->apiUserId(),
            ]);

            // 2. 동적 필드 생성
            if (! empty($data['fields'])) {
                foreach ($data['fields'] as $fieldData) {
                    CategoryField::create([
                        'tenant_id' => $this->tenantId(),
                        'category_id' => $category->id,
                        'field_key' => $fieldData['key'],
                        'field_name' => $fieldData['name'],
                        'field_type' => $fieldData['type'],
                        'is_required' => $fieldData['required'] ?? false,
                        'sort_order' => $fieldData['order'] ?? 999,
                        'default_value' => $fieldData['default'] ?? null,
                        'options' => $fieldData['options'] ?? null,
                        'description' => $fieldData['description'] ?? '',
                        'created_by' => $this->apiUserId(),
                    ]);
                }
            }

            // 3. 모델 및 BOM 템플릿 생성 (선택사항)
            if (! empty($data['create_model'])) {
                $this->createDefaultModel($category, $data['model_data'] ?? []);
            }

            return $this->getModelSetDetail($category->id);
        });
    }

    /**
     * 모델셋 수정
     */
    public function updateModelSet($categoryId, array $data): array
    {
        return DB::transaction(function () use ($categoryId, $data) {
            $category = Category::where('tenant_id', $this->tenantId())
                ->findOrFail($categoryId);

            // 카테고리 정보 업데이트
            $category->update([
                'name' => $data['name'] ?? $category->name,
                'description' => $data['description'] ?? $category->description,
                'sort_order' => $data['sort_order'] ?? $category->sort_order,
                'is_active' => $data['is_active'] ?? $category->is_active,
                'updated_by' => $this->apiUserId(),
            ]);

            // 필드 업데이트 (기존 필드 삭제 후 재생성)
            if (isset($data['fields'])) {
                CategoryField::where('category_id', $categoryId)->delete();

                foreach ($data['fields'] as $fieldData) {
                    CategoryField::create([
                        'tenant_id' => $this->tenantId(),
                        'category_id' => $categoryId,
                        'field_key' => $fieldData['key'],
                        'field_name' => $fieldData['name'],
                        'field_type' => $fieldData['type'],
                        'is_required' => $fieldData['required'] ?? false,
                        'sort_order' => $fieldData['order'] ?? 999,
                        'default_value' => $fieldData['default'] ?? null,
                        'options' => $fieldData['options'] ?? null,
                        'description' => $fieldData['description'] ?? '',
                        'created_by' => $this->apiUserId(),
                    ]);
                }
            }

            return $this->getModelSetDetail($categoryId);
        });
    }

    /**
     * 모델셋 삭제
     */
    public function deleteModelSet($categoryId): void
    {
        DB::transaction(function () use ($categoryId) {
            $category = Category::where('tenant_id', $this->tenantId())
                ->findOrFail($categoryId);

            // 연관된 데이터들 확인
            $hasProducts = Product::where('category_id', $categoryId)->exists();
            $hasChildren = Category::where('parent_id', $categoryId)->exists();

            if ($hasProducts || $hasChildren) {
                throw new \Exception(__('error.modelset.has_dependencies'));
            }

            // 필드 삭제
            CategoryField::where('category_id', $categoryId)->delete();

            // 카테고리 삭제 (소프트 삭제)
            $category->update(['deleted_by' => $this->apiUserId()]);
            $category->delete();
        });
    }

    /**
     * 모델셋 복제
     */
    public function cloneModelSet($categoryId, array $data): array
    {
        return DB::transaction(function () use ($categoryId, $data) {
            $originalCategory = Category::with('fields')
                ->where('tenant_id', $this->tenantId())
                ->findOrFail($categoryId);

            // 새로운 카테고리 생성
            $newCategory = Category::create([
                'tenant_id' => $this->tenantId(),
                'parent_id' => $originalCategory->parent_id,
                'code_group' => $originalCategory->code_group,
                'code' => $data['code'],
                'name' => $data['name'],
                'description' => $data['description'] ?? $originalCategory->description,
                'level' => $originalCategory->level,
                'sort_order' => $data['sort_order'] ?? 999,
                'profile_code' => $originalCategory->profile_code,
                'is_active' => $data['is_active'] ?? true,
                'created_by' => $this->apiUserId(),
            ]);

            // 필드 복제
            foreach ($originalCategory->fields as $field) {
                CategoryField::create([
                    'tenant_id' => $this->tenantId(),
                    'category_id' => $newCategory->id,
                    'field_key' => $field->field_key,
                    'field_name' => $field->field_name,
                    'field_type' => $field->field_type,
                    'is_required' => $field->is_required,
                    'sort_order' => $field->sort_order,
                    'default_value' => $field->default_value,
                    'options' => $field->options,
                    'description' => $field->description,
                    'created_by' => $this->apiUserId(),
                ]);
            }

            return $this->getModelSetDetail($newCategory->id);
        });
    }

    /**
     * 모델셋의 카테고리 필드 구조 조회
     */
    public function getModelSetCategoryFields($categoryId): array
    {
        $category = Category::with('fields')
            ->where('tenant_id', $this->tenantId())
            ->findOrFail($categoryId);

        return $this->generateFieldSchema($category->fields);
    }

    /**
     * 모델셋의 BOM 템플릿 목록
     */
    public function getModelSetBomTemplates($categoryId): Collection
    {
        // 해당 카테고리와 연관된 모델들의 BOM 템플릿들
        $models = $this->getRelatedModels($categoryId);

        $bomTemplates = collect();
        foreach ($models as $model) {
            foreach ($model['versions'] as $version) {
                $bomTemplates = $bomTemplates->merge($version['bom_templates']);
            }
        }

        return $bomTemplates;
    }

    /**
     * 견적 파라미터 조회 (동적 필드 기반)
     */
    public function getEstimateParameters($categoryId, array $filters = []): array
    {
        $category = Category::with('fields')
            ->where('tenant_id', $this->tenantId())
            ->findOrFail($categoryId);

        // 입력 파라미터 (사용자가 입력해야 하는 필드들)
        $inputFields = $category->fields
            ->filter(function ($field) {
                return in_array($field->field_key, [
                    'open_width', 'open_height', 'quantity',
                    'model_name', 'guide_rail_type', 'shutter_box',
                ]);
            })
            ->map(function ($field) {
                return [
                    'key' => $field->field_key,
                    'name' => $field->field_name,
                    'type' => $field->field_type,
                    'required' => $field->is_required,
                    'default' => $field->default_value,
                    'options' => $field->options,
                    'description' => $field->description,
                ];
            });

        // 계산 결과 필드 (자동으로 계산되는 필드들)
        $calculatedFields = $category->fields
            ->filter(function ($field) {
                return in_array($field->field_key, [
                    'make_width', 'make_height', 'calculated_weight',
                    'calculated_area', 'motor_bracket_size', 'motor_capacity',
                ]);
            })
            ->map(function ($field) {
                return [
                    'key' => $field->field_key,
                    'name' => $field->field_name,
                    'type' => $field->field_type,
                    'description' => $field->description,
                ];
            });

        return [
            'category' => [
                'id' => $category->id,
                'name' => $category->name,
                'code' => $category->code,
            ],
            'input_fields' => $inputFields->values(),
            'calculated_fields' => $calculatedFields->values(),
            'calculation_schema' => $this->getCalculationSchema($category->code),
        ];
    }

    /**
     * 모델셋 기반 BOM 계산
     */
    public function calculateModelSetBom($categoryId, array $parameters): array
    {
        $category = Category::where('tenant_id', $this->tenantId())
            ->findOrFail($categoryId);

        // BOM 템플릿 찾기 (기본 템플릿 사용)
        $bomTemplate = $this->findDefaultBomTemplate($categoryId, $parameters);

        if (! $bomTemplate) {
            throw new \Exception(__('error.bom_template.not_found'));
        }

        // 기존 BOM 계산 엔진 사용
        return $this->calculationEngine->calculateBOM(
            $bomTemplate->id,
            $parameters,
            $this->getCompanyName($category)
        );
    }

    /**
     * 카테고리와 연관된 모델들 조회
     */
    protected function getRelatedModels($categoryId): Collection
    {
        // 카테고리 코드 기반으로 모델 찾기
        $category = Category::findOrFail($categoryId);

        return Model::with(['versions.bomTemplates'])
            ->where('tenant_id', $this->tenantId())
            ->where('code', 'like', $category->code.'%')
            ->get()
            ->map(function ($model) {
                return [
                    'id' => $model->id,
                    'code' => $model->code,
                    'name' => $model->name,
                    'versions' => $model->versions->map(function ($version) {
                        return [
                            'id' => $version->id,
                            'version_no' => $version->version_no,
                            'status' => $version->status,
                            'bom_templates' => $version->bomTemplates,
                        ];
                    }),
                ];
            });
    }

    /**
     * 필드 스키마 생성
     */
    protected function generateFieldSchema(Collection $fields): array
    {
        return $fields->map(function ($field) {
            return [
                'key' => $field->field_key,
                'name' => $field->field_name,
                'type' => $field->field_type,
                'required' => $field->is_required,
                'order' => $field->sort_order,
                'default' => $field->default_value,
                'options' => $field->options,
                'description' => $field->description,
            ];
        })->sortBy('order')->values()->toArray();
    }

    /**
     * 기본 모델 생성
     */
    protected function createDefaultModel(Category $category, array $modelData): void
    {
        $model = Model::create([
            'tenant_id' => $this->tenantId(),
            'code' => $modelData['code'] ?? $category->code.'_MODEL',
            'name' => $modelData['name'] ?? $category->name.' 기본 모델',
            'description' => $modelData['description'] ?? '',
            'status' => 'DRAFT',
            'created_by' => $this->apiUserId(),
        ]);

        $version = ModelVersion::create([
            'tenant_id' => $this->tenantId(),
            'model_id' => $model->id,
            'version_no' => 'v1.0',
            'status' => 'DRAFT',
            'created_by' => $this->apiUserId(),
        ]);

        BomTemplate::create([
            'tenant_id' => $this->tenantId(),
            'model_version_id' => $version->id,
            'name' => $category->name.' 기본 BOM',
            'company_type' => $this->getCompanyName($category),
            'formula_version' => 'v1.0',
            'calculation_schema' => $this->getDefaultCalculationSchema($category),
            'created_by' => $this->apiUserId(),
        ]);
    }

    /**
     * 계산 스키마 조회
     */
    protected function getCalculationSchema(string $categoryCode): array
    {
        if ($categoryCode === 'screen_product') {
            return [
                'size_calculation' => 'kyungdong_screen_size',
                'weight_calculation' => 'screen_weight_calculation',
                'bracket_calculation' => 'motor_bracket_size',
            ];
        } elseif ($categoryCode === 'steel_product') {
            return [
                'size_calculation' => 'kyungdong_steel_size',
                'bracket_calculation' => 'motor_bracket_size',
                'round_bar_calculation' => 'round_bar_quantity',
            ];
        }

        return [];
    }

    /**
     * 기본 BOM 템플릿 찾기
     */
    protected function findDefaultBomTemplate($categoryId, array $parameters): ?BomTemplate
    {
        $models = $this->getRelatedModels($categoryId);

        foreach ($models as $model) {
            foreach ($model['versions'] as $version) {
                if ($version['status'] === 'RELEASED' && $version['bom_templates']->isNotEmpty()) {
                    return $version['bom_templates']->first();
                }
            }
        }

        return null;
    }

    /**
     * 업체명 조회
     */
    protected function getCompanyName(Category $category): string
    {
        // 테넌트 정보에서 업체명 조회하거나 기본값 사용
        return '경동기업'; // 임시 하드코딩
    }

    /**
     * 기본 계산 스키마 생성
     */
    protected function getDefaultCalculationSchema(Category $category): array
    {
        return [
            'calculation_type' => $category->code,
            'formulas' => $this->getCalculationSchema($category->code),
        ];
    }
}
