<?php

namespace App\Console\Commands;

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

/**
 * 경동기업(tenant_id=287) 품목 기준 데이터를 JSON으로 추출
 *
 * 추출 대상: item_pages, item_sections, item_fields,
 *           entity_relationships, categories, items, item_details, prices
 *
 * 사용법: php artisan kyungdong:export-item-master
 */
class ExportItemMasterDataCommand extends Command
{
    protected $signature = 'kyungdong:export-item-master';

    protected $description = '경동기업(tenant_id=287) 품목 기준 데이터를 JSON 파일로 추출';

    private const TENANT_ID = 287;

    private string $outputPath;

    public function handle(): int
    {
        $this->outputPath = database_path('seeders/data/kyungdong');

        if (! is_dir($this->outputPath)) {
            mkdir($this->outputPath, 0755, true);
        }

        $this->info('경동기업 품목 기준 데이터 추출 시작 (tenant_id=' . self::TENANT_ID . ')');
        $this->newLine();

        $this->exportItemPages();
        $this->exportItemSections();
        $this->exportItemFields();
        $this->exportEntityRelationships();
        $this->exportCategories();
        $this->exportItems();
        $this->exportItemDetails();
        $this->exportPrices();

        $this->newLine();
        $this->info('추출 완료! 경로: ' . $this->outputPath);

        return self::SUCCESS;
    }

    private function exportItemPages(): void
    {
        $rows = DB::table('item_pages')
            ->where('tenant_id', self::TENANT_ID)
            ->whereNull('deleted_at')
            ->get()
            ->map(fn ($row) => $this->addOriginalId($row))
            ->toArray();

        $this->writeJson('item_pages.json', $rows);
        $this->info("  item_pages: " . count($rows) . "건");
    }

    private function exportItemSections(): void
    {
        $rows = DB::table('item_sections')
            ->where('tenant_id', self::TENANT_ID)
            ->whereNull('deleted_at')
            ->get()
            ->map(fn ($row) => $this->addOriginalId($row))
            ->toArray();

        $this->writeJson('item_sections.json', $rows);
        $this->info("  item_sections: " . count($rows) . "건");
    }

    private function exportItemFields(): void
    {
        $rows = DB::table('item_fields')
            ->where('tenant_id', self::TENANT_ID)
            ->whereNull('deleted_at')
            ->get()
            ->map(fn ($row) => $this->addOriginalId($row))
            ->toArray();

        $this->writeJson('item_fields.json', $rows);
        $this->info("  item_fields: " . count($rows) . "건");
    }

    private function exportEntityRelationships(): void
    {
        // 참조 대상이 실제 존재하는 것만 추출
        $validPageIds = DB::table('item_pages')->where('tenant_id', self::TENANT_ID)->whereNull('deleted_at')->pluck('id');
        $validSectionIds = DB::table('item_sections')->where('tenant_id', self::TENANT_ID)->whereNull('deleted_at')->pluck('id');
        $validFieldIds = DB::table('item_fields')->where('tenant_id', self::TENANT_ID)->whereNull('deleted_at')->pluck('id');
        $validBomIds = DB::table('item_bom_items')->where('tenant_id', self::TENANT_ID)->whereNull('deleted_at')->pluck('id');

        $validIds = [
            'page' => $validPageIds->flip(),
            'section' => $validSectionIds->flip(),
            'field' => $validFieldIds->flip(),
            'bom' => $validBomIds->flip(),
        ];

        $rows = DB::table('entity_relationships')
            ->where('tenant_id', self::TENANT_ID)
            ->get()
            ->filter(function ($row) use ($validIds) {
                $parentValid = isset($validIds[$row->parent_type][$row->parent_id]);
                $childValid = isset($validIds[$row->child_type][$row->child_id]);

                return $parentValid && $childValid;
            })
            ->map(fn ($row) => $this->addOriginalId($row))
            ->values()
            ->toArray();

        $this->writeJson('entity_relationships.json', $rows);
        $this->info("  entity_relationships: " . count($rows) . "건");
    }

    private function exportCategories(): void
    {
        $rows = DB::table('categories')
            ->where('tenant_id', self::TENANT_ID)
            ->whereNull('deleted_at')
            ->orderByRaw('COALESCE(parent_id, 0), sort_order, id')
            ->get()
            ->map(fn ($row) => $this->addOriginalId($row))
            ->toArray();

        $this->writeJson('categories.json', $rows);
        $this->info("  categories: " . count($rows) . "건");
    }

    private function exportItems(): void
    {
        $rows = DB::table('items')
            ->where('tenant_id', self::TENANT_ID)
            ->whereNull('deleted_at')
            ->orderBy('id')
            ->get()
            ->map(fn ($row) => $this->addOriginalId($row))
            ->toArray();

        $this->writeJson('items.json', $rows);
        $this->info("  items: " . count($rows) . "건");
    }

    private function exportItemDetails(): void
    {
        $itemIds = DB::table('items')
            ->where('tenant_id', self::TENANT_ID)
            ->whereNull('deleted_at')
            ->pluck('id');

        $rows = DB::table('item_details')
            ->whereIn('item_id', $itemIds)
            ->get()
            ->map(fn ($row) => $this->addOriginalId($row))
            ->toArray();

        $this->writeJson('item_details.json', $rows);
        $this->info("  item_details: " . count($rows) . "건");
    }

    private function exportPrices(): void
    {
        $rows = DB::table('prices')
            ->where('tenant_id', self::TENANT_ID)
            ->whereNull('deleted_at')
            ->orderBy('id')
            ->get()
            ->map(fn ($row) => $this->addOriginalId($row))
            ->toArray();

        $this->writeJson('prices.json', $rows);
        $this->info("  prices: " . count($rows) . "건");
    }

    /**
     * _original_id 추가 + id 제거
     */
    private function addOriginalId(object $row): array
    {
        $data = (array) $row;
        $data['_original_id'] = $data['id'];
        unset($data['id']);

        return $data;
    }

    private function writeJson(string $filename, array $data): void
    {
        $path = $this->outputPath . '/' . $filename;
        file_put_contents(
            $path,
            json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
        );
    }
}
