<?php

namespace App\Services\Design;

use App\Models\Calculation\CalculationConfig;
use App\Models\Design\BomTemplate;
use App\Services\Calculation\CalculationEngine;
use App\Services\Service;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class BomCalculationService extends Service
{
    protected CalculationEngine $calculationEngine;

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

    /**
     * 견적 파라미터 조회
     *
     * @param  int  $modelId  모델 ID
     * @param  string|null  $companyName  업체명
     */
    public function getEstimateParameters(int $modelId, ?string $companyName = null): array
    {
        try {
            // 모델의 기본 BOM 템플릿 조회
            $bomTemplate = BomTemplate::with(['modelVersion.model'])
                ->where('tenant_id', $this->tenantId())
                ->whereHas('modelVersion', function ($query) use ($modelId) {
                    $query->whereHas('model', function ($q) use ($modelId) {
                        $q->where('id', $modelId);
                    });
                })
                ->where('is_primary', true)
                ->first();

            if (! $bomTemplate) {
                throw new \Exception("모델 ID {$modelId}에 대한 BOM 템플릿을 찾을 수 없습니다.");
            }

            // 파라미터 스키마 추출
            $parameters = $this->calculationEngine->getRequiredParameters($bomTemplate->id);

            // 업체별 추가 파라미터가 있는지 확인
            if ($companyName) {
                $companyParameters = $this->getCompanySpecificParameters($companyName);
                if ($companyParameters) {
                    $parameters = array_merge_recursive($parameters, $companyParameters);
                }
            }

            return [
                'model_info' => [
                    'id' => $bomTemplate->modelVersion->model->id,
                    'name' => $bomTemplate->modelVersion->model->name ?? '모델명 없음',
                    'version' => $bomTemplate->modelVersion->version_no ?? 'v1.0',
                    'bom_template_id' => $bomTemplate->id,
                ],
                'company_info' => [
                    'company_type' => $bomTemplate->company_type,
                    'formula_version' => $bomTemplate->formula_version,
                    'requested_company' => $companyName,
                ],
                'parameters' => $parameters,
                'calculation_preview' => true,
            ];

        } catch (\Exception $e) {
            Log::error('견적 파라미터 조회 실패', [
                'model_id' => $modelId,
                'company_name' => $companyName,
                'error' => $e->getMessage(),
            ]);

            throw $e;
        }
    }

    /**
     * BOM 계산 실행
     *
     * @param  int  $bomTemplateId  BOM 템플릿 ID
     * @param  array  $parameters  입력 파라미터
     * @param  string|null  $companyName  업체명
     */
    public function calculateBomEstimate(int $bomTemplateId, array $parameters, ?string $companyName = null): array
    {
        try {
            DB::beginTransaction();

            // BOM 템플릿 조회 및 권한 확인
            $bomTemplate = BomTemplate::where('tenant_id', $this->tenantId())
                ->findOrFail($bomTemplateId);

            // 업체명이 지정된 경우 BOM 템플릿 업데이트
            if ($companyName && $bomTemplate->company_type !== $companyName) {
                $bomTemplate->update(['company_type' => $companyName]);
            }

            // 계산 엔진 실행
            $result = $this->calculationEngine->calculateBOM($bomTemplateId, $parameters, $companyName);

            // 계산 이력 로그 저장 (선택사항)
            $this->logCalculationHistory($bomTemplateId, $parameters, $result, $companyName);

            DB::commit();

            return [
                'success' => $result['success'],
                'data' => $result['success'] ? $result : null,
                'error' => $result['success'] ? null : $result['error'],
            ];

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('BOM 계산 실행 실패', [
                'bom_template_id' => $bomTemplateId,
                'parameters' => $parameters,
                'company_name' => $companyName,
                'error' => $e->getMessage(),
            ]);

            return [
                'success' => false,
                'data' => null,
                'error' => $e->getMessage(),
            ];
        }
    }

    /**
     * 업체별 산출식 목록 조회
     *
     * @param  string  $companyName  업체명
     */
    public function getCompanyFormulas(string $companyName): array
    {
        $formulas = CalculationConfig::getActiveFormulasForCompany($this->tenantId(), $companyName);

        return [
            'company_name' => $companyName,
            'total_formulas' => count($formulas),
            'formulas' => array_map(function ($formula) {
                return [
                    'type' => $formula['formula_type'],
                    'version' => $formula['version'],
                    'description' => $formula['description'],
                    'parameters' => $formula['parameters'],
                    'updated_at' => $formula['updated_at'],
                ];
            }, $formulas),
        ];
    }

    /**
     * 업체별 산출식 등록/수정
     *
     * @param  string  $companyName  업체명
     * @param  string  $formulaType  산출식 타입
     * @param  array  $formulaData  산출식 데이터
     */
    public function saveCompanyFormula(string $companyName, string $formulaType, array $formulaData): array
    {
        try {
            DB::beginTransaction();

            // 기존 산출식이 있는지 확인
            $existingFormula = CalculationConfig::getLatestFormula($this->tenantId(), $companyName, $formulaType);

            if ($existingFormula) {
                // 버전 업그레이드
                $newVersion = $this->incrementVersion($existingFormula->version);
                $existingFormula->update(['is_active' => false]); // 기존 비활성화
            } else {
                $newVersion = 'v1.0';
            }

            // 새 산출식 생성
            $formula = CalculationConfig::create([
                'tenant_id' => $this->tenantId(),
                'company_name' => $companyName,
                'formula_type' => $formulaType,
                'version' => $newVersion,
                'formula_expression' => $formulaData['formula_expression'],
                'parameters' => $formulaData['parameters'],
                'conditions' => $formulaData['conditions'] ?? null,
                'validation_rules' => $formulaData['validation_rules'] ?? null,
                'description' => $formulaData['description'] ?? null,
                'is_active' => true,
                'created_by' => $this->apiUserId(),
            ]);

            DB::commit();

            return [
                'id' => $formula->id,
                'company_name' => $formula->company_name,
                'formula_type' => $formula->formula_type,
                'version' => $formula->version,
                'is_active' => $formula->is_active,
                'created_at' => $formula->created_at,
            ];

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('업체별 산출식 저장 실패', [
                'company_name' => $companyName,
                'formula_type' => $formulaType,
                'error' => $e->getMessage(),
            ]);

            throw $e;
        }
    }

    /**
     * 업체별 추가 파라미터 조회
     */
    protected function getCompanySpecificParameters(string $companyName): ?array
    {
        // 업체별 특수 파라미터가 있는지 확인
        $companyConfig = CalculationConfig::forTenant($this->tenantId())
            ->forCompany($companyName)
            ->forType('additional_parameters')
            ->active()
            ->latest()
            ->first();

        return $companyConfig ? $companyConfig->parameters : null;
    }

    /**
     * 계산 이력 로그 저장
     */
    protected function logCalculationHistory(int $bomTemplateId, array $parameters, array $result, ?string $companyName): void
    {
        // 필요에 따라 계산 이력을 별도 테이블에 저장
        Log::info('BOM 계산 완료', [
            'bom_template_id' => $bomTemplateId,
            'company_name' => $companyName,
            'parameters' => $parameters,
            'success' => $result['success'],
            'calculated_items_count' => $result['success'] ? count($result['bom_items']) : 0,
            'calculated_by' => $this->apiUserId(),
        ]);
    }

    /**
     * 버전 번호 증가
     */
    protected function incrementVersion(string $currentVersion): string
    {
        if (preg_match('/^v(\d+)\.(\d+)$/', $currentVersion, $matches)) {
            $major = (int) $matches[1];
            $minor = (int) $matches[2];

            return "v{$major}.".($minor + 1);
        }

        return 'v1.0';
    }
}
