<?php

namespace App\Console\Commands;

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

/**
 * 5130 가격표 품목 → SAM items 마이그레이션
 *
 * 대상 테이블:
 * - KDunitprice → items (SM, RM, CS)
 * - price_raw_materials → items (RM)
 * - price_bend → items (PT)
 */
#[AsCommand(name: 'migrate:5130-price-items', description: '5130 가격표(KDunitprice, price_raw_materials, price_bend) → SAM items 마이그레이션')]
class Migrate5130PriceItems extends Command
{
    protected $signature = 'migrate:5130-price-items
                            {--tenant_id=287 : Target tenant ID (default: 287 경동기업)}
                            {--dry-run : 실제 저장 없이 시뮬레이션만 수행}
                            {--step=all : 실행할 단계 (all|kdunitprice|raw_materials|bend)}
                            {--rollback : 마이그레이션 롤백}
                            {--limit=0 : 테스트용 레코드 수 제한 (0=전체)}';

    // 5130 DB 연결 (chandj)
    private string $sourceDb = 'chandj';

    // SAM DB 연결
    private string $targetDb = 'mysql';

    // 통계
    private array $stats = [
        'kdunitprice' => ['total' => 0, 'migrated' => 0, 'skipped' => 0],
        'raw_materials' => ['total' => 0, 'migrated' => 0, 'skipped' => 0],
        'bend' => ['total' => 0, 'migrated' => 0, 'skipped' => 0],
    ];

    public function handle(): int
    {
        $tenantId = (int) $this->option('tenant_id');
        $dryRun = $this->option('dry-run');
        $step = $this->option('step');
        $rollback = $this->option('rollback');
        $limit = (int) $this->option('limit');

        $this->info('╔══════════════════════════════════════════════════════════════╗');
        $this->info('║   5130 가격표 → SAM items 마이그레이션                        ║');
        $this->info('╚══════════════════════════════════════════════════════════════╝');
        $this->newLine();
        $this->info("📌 Tenant ID: {$tenantId}");
        $this->info('📌 Mode: '.($dryRun ? '🔍 DRY-RUN (시뮬레이션)' : '⚡ LIVE'));
        $this->info("📌 Step: {$step}");
        if ($limit > 0) {
            $this->warn("📌 Limit: {$limit} records (테스트 모드)");
        }
        $this->newLine();

        if ($rollback) {
            return $this->rollbackMigration($tenantId, $dryRun);
        }

        $steps = $step === 'all'
            ? ['kdunitprice', 'raw_materials', 'bend']
            : [$step];

        foreach ($steps as $currentStep) {
            $this->line('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
            $this->info(">>> Step: {$currentStep}");
            $this->newLine();

            match ($currentStep) {
                'kdunitprice' => $this->migrateKDunitprice($tenantId, $dryRun, $limit),
                'raw_materials' => $this->migratePriceRawMaterials($tenantId, $dryRun, $limit),
                'bend' => $this->migratePriceBend($tenantId, $dryRun, $limit),
                default => $this->error("Unknown step: {$currentStep}"),
            };

            $this->newLine();
        }

        $this->showSummary();

        return self::SUCCESS;
    }

    /**
     * KDunitprice → items (SM, RM, CS)
     */
    private function migrateKDunitprice(int $tenantId, bool $dryRun, int $limit): void
    {
        $this->info('📦 Migrating KDunitprice → items (SM, RM, CS)...');

        $query = DB::connection($this->sourceDb)->table('KDunitprice')
            ->whereNull('is_deleted')
            ->orWhere('is_deleted', 0);

        if ($limit > 0) {
            $query->limit($limit);
        }

        $items = $query->get();
        $this->stats['kdunitprice']['total'] = $items->count();
        $this->line("Found {$items->count()} records");

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

        foreach ($items as $item) {
            // 이미 존재하는지 확인 (code 기준)
            $exists = DB::connection($this->targetDb)->table('items')
                ->where('tenant_id', $tenantId)
                ->where('code', $item->prodcode)
                ->whereNull('deleted_at')
                ->exists();

            if ($exists) {
                $this->stats['kdunitprice']['skipped']++;
                $bar->advance();

                continue;
            }

            // item_type 결정
            $itemType = $this->determineItemType($item->item_div);

            // 단가 파싱 (콤마 제거)
            $unitPrice = $this->parseNumber($item->unitprice);

            $itemData = [
                'tenant_id' => $tenantId,
                'item_type' => $itemType,
                'item_category' => $item->item_div,
                'code' => $item->prodcode,
                'name' => $item->item_name ?: '(이름없음)',
                'unit' => $item->unit ?: 'EA',
                'attributes' => json_encode([
                    'spec' => $item->spec,
                    'unit_price' => $unitPrice,
                    'update_log' => $item->update_log,
                    'source' => '5130',
                    'source_table' => 'KDunitprice',
                    'source_id' => $item->num,
                ], JSON_UNESCAPED_UNICODE),
                'is_active' => true,
                'created_at' => now(),
                'updated_at' => now(),
            ];

            if (! $dryRun) {
                DB::connection($this->targetDb)->table('items')->insert($itemData);
            }

            $this->stats['kdunitprice']['migrated']++;
            $bar->advance();
        }

        $bar->finish();
        $this->newLine();
        $this->info("✅ KDunitprice 완료: {$this->stats['kdunitprice']['migrated']} migrated, {$this->stats['kdunitprice']['skipped']} skipped");
    }

    /**
     * price_raw_materials → items (RM)
     * 최신 버전(registedate)만 마이그레이션
     */
    private function migratePriceRawMaterials(int $tenantId, bool $dryRun, int $limit): void
    {
        $this->info('📦 Migrating price_raw_materials → items (RM)...');

        // 최신 registedate 조회
        $latestRecord = DB::connection($this->sourceDb)->table('price_raw_materials')
            ->whereNull('is_deleted')
            ->orWhere('is_deleted', 0)
            ->orderBy('registedate', 'desc')
            ->first();

        if (! $latestRecord) {
            $this->warn('No records found in price_raw_materials');

            return;
        }

        $this->line("Latest version: {$latestRecord->registedate}");

        $itemList = json_decode($latestRecord->itemList ?? '[]', true);
        if (empty($itemList)) {
            $this->warn('Empty itemList in latest record');

            return;
        }

        $totalItems = count($itemList);
        if ($limit > 0 && $limit < $totalItems) {
            $itemList = array_slice($itemList, 0, $limit);
        }

        $this->stats['raw_materials']['total'] = count($itemList);
        $this->line('Found '.count($itemList).' items in itemList');

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

        $orderNo = 0;
        foreach ($itemList as $row) {
            $orderNo++;

            // 코드 생성: col14가 있으면 사용, 없으면 자동생성
            $code = ! empty($row['col14'])
                ? $row['col14']
                : $this->generateCode('RM', $latestRecord->registedate, $orderNo);

            // 이미 존재하는지 확인
            $exists = DB::connection($this->targetDb)->table('items')
                ->where('tenant_id', $tenantId)
                ->where('code', $code)
                ->whereNull('deleted_at')
                ->exists();

            if ($exists) {
                $this->stats['raw_materials']['skipped']++;
                $bar->advance();

                continue;
            }

            // 품목명 생성
            $name = trim(($row['col1'] ?? '').' '.($row['col2'] ?? '')) ?: '(이름없음)';

            // item_category 결정
            $itemCategory = $this->determineRawMaterialCategory($row['col1'] ?? '');

            $itemData = [
                'tenant_id' => $tenantId,
                'item_type' => 'RM',
                'item_category' => $itemCategory,
                'code' => $code,
                'name' => $name,
                'unit' => 'kg',
                'attributes' => json_encode([
                    'product_type' => $row['col1'] ?? null,
                    'sub_type' => $row['col2'] ?? null,
                    'length' => $this->parseNumber($row['col3'] ?? null),
                    'thickness' => $this->parseNumber($row['col4'] ?? null),
                    'specific_gravity' => $this->parseNumber($row['col5'] ?? null),
                    'area_per_unit' => $this->parseNumber($row['col6'] ?? null),
                    'weight_per_sqm' => $this->parseNumber($row['col7'] ?? null),
                    'purchase_price_per_kg' => $this->parseNumber($row['col8'] ?? null),
                    'price_per_sqm_with_loss' => $this->parseNumber($row['col9'] ?? null),
                    'processing_cost' => $this->parseNumber($row['col10'] ?? null),
                    'mimi' => $this->parseNumber($row['col11'] ?? null),
                    'total' => $this->parseNumber($row['col12'] ?? null),
                    'total_with_labor' => $this->parseNumber($row['col13'] ?? null),
                    'non_certified_code' => $row['col14'] ?? null,
                    'non_certified_price' => $this->parseNumber($row['col15'] ?? null),
                    'source' => '5130',
                    'source_table' => 'price_raw_materials',
                    'source_id' => $latestRecord->num,
                    'source_version' => $latestRecord->registedate,
                    'source_order' => $orderNo,
                ], JSON_UNESCAPED_UNICODE),
                'is_active' => true,
                'created_at' => now(),
                'updated_at' => now(),
            ];

            if (! $dryRun) {
                DB::connection($this->targetDb)->table('items')->insert($itemData);
            }

            $this->stats['raw_materials']['migrated']++;
            $bar->advance();
        }

        $bar->finish();
        $this->newLine();
        $this->info("✅ price_raw_materials 완료: {$this->stats['raw_materials']['migrated']} migrated, {$this->stats['raw_materials']['skipped']} skipped");
    }

    /**
     * price_bend → items (PT)
     * 최신 버전(registedate)만 마이그레이션
     */
    private function migratePriceBend(int $tenantId, bool $dryRun, int $limit): void
    {
        $this->info('📦 Migrating price_bend → items (PT)...');

        // 최신 registedate 조회
        $latestRecord = DB::connection($this->sourceDb)->table('price_bend')
            ->whereNull('is_deleted')
            ->orWhere('is_deleted', 0)
            ->orderBy('registedate', 'desc')
            ->first();

        if (! $latestRecord) {
            $this->warn('No records found in price_bend');

            return;
        }

        $this->line("Latest version: {$latestRecord->registedate}");

        $itemList = json_decode($latestRecord->itemList ?? '[]', true);
        if (empty($itemList)) {
            $this->warn('Empty itemList in latest record');

            return;
        }

        $totalItems = count($itemList);
        if ($limit > 0 && $limit < $totalItems) {
            $itemList = array_slice($itemList, 0, $limit);
        }

        $this->stats['bend']['total'] = count($itemList);
        $this->line('Found '.count($itemList).' items in itemList');

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

        $orderNo = 0;
        foreach ($itemList as $row) {
            $orderNo++;

            // 코드 자동생성
            $code = $this->generateCode('PT', $latestRecord->registedate, $orderNo);

            // 이미 존재하는지 확인
            $exists = DB::connection($this->targetDb)->table('items')
                ->where('tenant_id', $tenantId)
                ->where('code', $code)
                ->whereNull('deleted_at')
                ->exists();

            if ($exists) {
                $this->stats['bend']['skipped']++;
                $bar->advance();

                continue;
            }

            // 품목명 생성
            $name = trim(($row['col1'] ?? '').' '.($row['col2'] ?? '')) ?: '(이름없음)';

            // item_category 결정 (STEEL/ALUMINUM 등)
            $itemCategory = $this->determineBendCategory($row['col1'] ?? '');

            $itemData = [
                'tenant_id' => $tenantId,
                'item_type' => 'PT',
                'item_category' => $itemCategory,
                'code' => $code,
                'name' => $name,
                'unit' => '㎡',
                'attributes' => json_encode([
                    'material_type' => $row['col1'] ?? null,
                    'material_sub' => $row['col2'] ?? null,
                    'width' => $this->parseNumber($row['col3'] ?? null),
                    'length' => $this->parseNumber($row['col4'] ?? null),
                    'thickness' => $this->parseNumber($row['col5'] ?? null),
                    'specific_gravity' => $this->parseNumber($row['col6'] ?? null),
                    'area' => $this->parseNumber($row['col7'] ?? null),
                    'weight' => $this->parseNumber($row['col8'] ?? null),
                    'purchase_price_per_kg' => $this->parseNumber($row['col9'] ?? null),
                    'loss_premium_price' => $this->parseNumber($row['col10'] ?? null),
                    'material_cost' => $this->parseNumber($row['col11'] ?? null),
                    'selling_price' => $this->parseNumber($row['col12'] ?? null),
                    'processing_cost_per_sqm' => $this->parseNumber($row['col13'] ?? null),
                    'processing_cost' => $this->parseNumber($row['col14'] ?? null),
                    'total' => $this->parseNumber($row['col15'] ?? null),
                    'price_per_sqm' => $this->parseNumber($row['col16'] ?? null),
                    'selling_price_per_sqm' => $this->parseNumber($row['col17'] ?? null),
                    'price_per_kg' => $this->parseNumber($row['col18'] ?? null),
                    'source' => '5130',
                    'source_table' => 'price_bend',
                    'source_id' => $latestRecord->num,
                    'source_version' => $latestRecord->registedate,
                    'source_order' => $orderNo,
                ], JSON_UNESCAPED_UNICODE),
                'is_active' => true,
                'created_at' => now(),
                'updated_at' => now(),
            ];

            if (! $dryRun) {
                DB::connection($this->targetDb)->table('items')->insert($itemData);
            }

            $this->stats['bend']['migrated']++;
            $bar->advance();
        }

        $bar->finish();
        $this->newLine();
        $this->info("✅ price_bend 완료: {$this->stats['bend']['migrated']} migrated, {$this->stats['bend']['skipped']} skipped");
    }

    /**
     * item_type 결정 (KDunitprice용)
     *
     * 5130 item_div → SAM item_type 매핑:
     * - [원재료] → RM (원자재)
     * - [부재료] → SM (부자재)
     * - [상품], [제품] → FG (완제품)
     * - [반제품] → PT (부품)
     * - [무형상품] → CS (소모품/서비스)
     *
     * 주의: 조건 순서가 중요함 (더 구체적인 조건을 먼저 체크)
     * - '반제품'을 '제품'보다 먼저 체크
     * - '무형상품'을 '상품'보다 먼저 체크
     */
    private function determineItemType(?string $itemDiv): string
    {
        if (empty($itemDiv)) {
            return 'SM';
        }

        $lower = mb_strtolower($itemDiv);

        // 1. 부품 판별 (반제품) - '제품'보다 먼저!
        if (str_contains($lower, '반제품')) {
            return 'PT';
        }

        // 2. 소모품 판별 (무형상품) - '상품'보다 먼저!
        if (str_contains($lower, '무형') || str_contains($lower, '소모품') || str_contains($lower, 'consumable') || str_contains($lower, '소모')) {
            return 'CS';
        }

        // 3. 완제품 판별 (상품, 제품)
        if (str_contains($lower, '상품') || str_contains($lower, '제품')) {
            return 'FG';
        }

        // 4. 원자재 판별 (원재료)
        if (str_contains($lower, '원자재') || str_contains($lower, '원재료') || str_contains($lower, 'raw') || str_contains($lower, '원료')) {
            return 'RM';
        }

        // 5. 기본값: 부자재 (부재료 포함)
        return 'SM';
    }

    /**
     * 원자재 카테고리 결정
     */
    private function determineRawMaterialCategory(?string $productType): string
    {
        if (empty($productType)) {
            return 'GENERAL';
        }

        $lower = mb_strtolower($productType);

        if (str_contains($lower, '슬랫') || str_contains($lower, 'slat')) {
            return 'SLAT';
        }
        if (str_contains($lower, '알루미늄') || str_contains($lower, 'aluminum') || str_contains($lower, 'al')) {
            return 'ALUMINUM';
        }
        if (str_contains($lower, '스틸') || str_contains($lower, 'steel')) {
            return 'STEEL';
        }

        return 'GENERAL';
    }

    /**
     * 절곡 카테고리 결정
     */
    private function determineBendCategory(?string $materialType): string
    {
        if (empty($materialType)) {
            return 'GENERAL';
        }

        $lower = mb_strtolower($materialType);

        if (str_contains($lower, '스틸') || str_contains($lower, 'steel') || str_contains($lower, '철')) {
            return 'STEEL';
        }
        if (str_contains($lower, '알루미늄') || str_contains($lower, 'aluminum') || str_contains($lower, 'al')) {
            return 'ALUMINUM';
        }

        return 'BENDING';
    }

    /**
     * 코드 생성
     */
    private function generateCode(string $prefix, ?string $date, int $orderNo): string
    {
        $dateStr = $date ? str_replace('-', '', $date) : date('Ymd');

        return sprintf('%s-%s-%03d', $prefix, $dateStr, $orderNo);
    }

    /**
     * 숫자 파싱 (콤마, 공백 제거)
     */
    private function parseNumber(mixed $value): ?float
    {
        if ($value === null || $value === '') {
            return null;
        }

        if (is_numeric($value)) {
            return (float) $value;
        }

        $cleaned = preg_replace('/[^\d.-]/', '', (string) $value);

        return is_numeric($cleaned) ? (float) $cleaned : null;
    }

    /**
     * 롤백
     */
    private function rollbackMigration(int $tenantId, bool $dryRun): int
    {
        $this->warn('╔══════════════════════════════════════════════════════════════╗');
        $this->warn('║   ⚠️  롤백 모드                                               ║');
        $this->warn('╚══════════════════════════════════════════════════════════════╝');

        if (! $this->confirm('5130 가격표에서 마이그레이션된 모든 데이터를 삭제하시겠습니까?')) {
            $this->info('롤백 취소됨');

            return self::SUCCESS;
        }

        $tables = ['KDunitprice', 'price_raw_materials', 'price_bend'];

        foreach ($tables as $table) {
            $count = DB::connection($this->targetDb)->table('items')
                ->where('tenant_id', $tenantId)
                ->whereRaw("JSON_EXTRACT(attributes, '$.source_table') = ?", [$table])
                ->count();

            if (! $dryRun) {
                DB::connection($this->targetDb)->table('items')
                    ->where('tenant_id', $tenantId)
                    ->whereRaw("JSON_EXTRACT(attributes, '$.source_table') = ?", [$table])
                    ->delete();
            }

            $this->line("Deleted {$count} items from {$table}");
        }

        $this->info('✅ 롤백 완료');

        return self::SUCCESS;
    }

    /**
     * 요약 출력
     */
    private function showSummary(): void
    {
        $this->newLine();
        $this->info('╔══════════════════════════════════════════════════════════════╗');
        $this->info('║   📊 마이그레이션 결과 요약                                    ║');
        $this->info('╚══════════════════════════════════════════════════════════════╝');

        $this->table(
            ['Source Table', 'Total', 'Migrated', 'Skipped'],
            [
                ['KDunitprice', $this->stats['kdunitprice']['total'], $this->stats['kdunitprice']['migrated'], $this->stats['kdunitprice']['skipped']],
                ['price_raw_materials', $this->stats['raw_materials']['total'], $this->stats['raw_materials']['migrated'], $this->stats['raw_materials']['skipped']],
                ['price_bend', $this->stats['bend']['total'], $this->stats['bend']['migrated'], $this->stats['bend']['skipped']],
            ]
        );

        $totalMigrated = $this->stats['kdunitprice']['migrated']
            + $this->stats['raw_materials']['migrated']
            + $this->stats['bend']['migrated'];

        $this->newLine();
        $this->info("🎉 총 {$totalMigrated}개 품목 마이그레이션 완료!");
    }
}
