<?php

namespace App\Console\Commands;

use Illuminate\Console\Attributes\AsCommand;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

#[AsCommand(name: 'items:normalize-dimensions', description: '품목 attributes에서 thickness/width/length 정규화')]
class NormalizeItemDimensions extends Command
{
    protected $signature = 'items:normalize-dimensions
                            {--tenant_id=287 : Target tenant ID (default: 287 경동기업)}
                            {--dry-run : 기본 모드 - 변경 예정 목록만 출력}
                            {--execute : 실제 DB 업데이트 수행}';

    protected $description = '101_specification_1/2/3에서 thickness/width/length를 추출하여 attributes에 정규화';

    private int $updatedCount = 0;

    private int $skippedCount = 0;

    private array $changes = [];

    public function handle(): int
    {
        $tenantId = (int) $this->option('tenant_id');
        $execute = $this->option('execute');
        $dryRun = ! $execute;

        $this->info('=== 품목 치수 정규화 ===');
        $this->info("Tenant ID: {$tenantId}");
        $this->info('Mode: '.($dryRun ? 'DRY-RUN (미리보기)' : 'EXECUTE (실행)'));
        $this->newLine();

        $items = DB::table('items')
            ->where('tenant_id', $tenantId)
            ->whereNull('deleted_at')
            ->whereRaw("JSON_EXTRACT(attributes, '$.\"101_specification_1\"') IS NOT NULL")
            ->get();

        $this->info("대상 품목: {$items->count()}건 (101_specification_1 존재)");
        $this->newLine();

        $bar = $this->output->createProgressBar($items->count());
        $bar->start();

        foreach ($items as $item) {
            $this->processItem($item, $dryRun);
            $bar->advance();
        }

        $bar->finish();
        $this->newLine(2);

        $this->showResults($dryRun);

        return self::SUCCESS;
    }

    private function processItem(object $item, bool $dryRun): void
    {
        $attributes = json_decode($item->attributes, true) ?? [];

        $spec1 = $attributes['101_specification_1'] ?? null;
        $spec2 = $attributes['102_specification_2'] ?? null;
        $spec3 = $attributes['103_specification_3'] ?? null;

        $existingThickness = $attributes['thickness'] ?? null;
        $existingWidth = $attributes['width'] ?? null;
        $existingLength = $attributes['length'] ?? null;

        $changed = false;
        $changeDetails = [];

        // thickness 추출: spec1에서 숫자 추출 (t/T 제거)
        if ($spec1 !== null && $spec1 !== '' && $existingThickness === null) {
            $thickness = $this->extractThickness($spec1);
            if ($thickness !== null) {
                $attributes['thickness'] = $thickness;
                $changeDetails[] = "thickness: {$spec1} → {$thickness}";
                $changed = true;
            }
        }

        // width 추출: spec2에서 순수 숫자만
        if ($spec2 !== null && $spec2 !== '' && $existingWidth === null) {
            $width = $this->extractNumeric($spec2);
            if ($width !== null) {
                $attributes['width'] = $width;
                $changeDetails[] = "width: {$spec2} → {$width}";
                $changed = true;
            }
        }

        // length 추출: spec3에서 순수 숫자만 (c, P/L, 문자 포함 시 스킵)
        if ($spec3 !== null && $spec3 !== '' && $existingLength === null) {
            $length = $this->extractLength($spec3);
            if ($length !== null) {
                $attributes['length'] = $length;
                $changeDetails[] = "length: {$spec3} → {$length}";
                $changed = true;
            }
        }

        if ($changed) {
            $this->changes[] = [
                'id' => $item->id,
                'name' => $item->name,
                'changes' => implode(', ', $changeDetails),
            ];

            if (! $dryRun) {
                DB::table('items')
                    ->where('id', $item->id)
                    ->update(['attributes' => json_encode($attributes, JSON_UNESCAPED_UNICODE)]);
            }

            $this->updatedCount++;
        } else {
            $this->skippedCount++;
        }
    }

    /**
     * thickness 추출: "t1.2", "T1.2", "1.2", "egi1.17" → 숫자
     * 패턴: 선행 문자(t/T/영문) 제거 후 숫자 추출
     */
    private function extractThickness(?string $value): ?string
    {
        if ($value === null || trim($value) === '') {
            return null;
        }

        $cleaned = trim($value);

        // "t1.2", "T1.2" → "1.2"
        $cleaned = preg_replace('/^[tT]/', '', $cleaned);

        // "egi1.17", "sus1.2" → 영문자 제거 후 숫자 추출
        if (preg_match('/(\d+(?:\.\d+)?)/', $cleaned, $matches)) {
            return $matches[1];
        }

        return null;
    }

    /**
     * 순수 숫자만 추출 (정수/소수)
     * "1219" → "1219", "1219.5" → "1219.5"
     * "c" → null, "" → null, "P/L" → null
     */
    private function extractNumeric(?string $value): ?string
    {
        if ($value === null || trim($value) === '') {
            return null;
        }

        $cleaned = trim($value);

        // 순수 숫자 (정수/소수)만 허용
        if (preg_match('/^\d+(?:\.\d+)?$/', $cleaned)) {
            return $cleaned;
        }

        return null;
    }

    /**
     * length 추출: "3000" → "3000", "3000 P/L" → "3000", "c" → null
     * 선행 숫자가 있고 뒤에 공백+문자(P/L 등)가 붙는 경우 숫자만 추출
     */
    private function extractLength(?string $value): ?string
    {
        if ($value === null || trim($value) === '') {
            return null;
        }

        $cleaned = trim($value);

        // 순수 숫자
        if (preg_match('/^\d+(?:\.\d+)?$/', $cleaned)) {
            return $cleaned;
        }

        // "3000 P/L" → "3000" (숫자로 시작하고 뒤에 공백+문자)
        if (preg_match('/^(\d+(?:\.\d+)?)\s+/', $cleaned, $matches)) {
            return $matches[1];
        }

        // "c", "P/L" 등 숫자 없는 경우
        return null;
    }

    private function showResults(bool $dryRun): void
    {
        $this->info('=== 결과 ===');
        $this->info("변경 대상: {$this->updatedCount}건");
        $this->info("스킵 (변경 불필요): {$this->skippedCount}건");
        $this->newLine();

        if (! empty($this->changes)) {
            $this->table(
                ['ID', '품목명', '변경 내용'],
                array_map(fn ($c) => [$c['id'], mb_substr($c['name'], 0, 30), $c['changes']], $this->changes)
            );
        }

        if ($dryRun) {
            $this->newLine();
            $this->warn('DRY-RUN 모드입니다. 실제 적용하려면 --execute 옵션을 사용하세요:');
            $this->line('  php artisan items:normalize-dimensions --execute');
        } else {
            $this->newLine();
            $this->info("총 {$this->updatedCount}건 업데이트 완료");
        }
    }
}
