<?php

namespace App\Services\ItemMaster;

use App\Models\ItemMaster\ItemField;
use App\Services\Service;
use Illuminate\Support\Facades\DB;

class ItemDataService extends Service
{
    /**
     * 필드 값을 적절한 테이블/컬럼에 저장
     *
     * @param  string  $sourceTable  대상 테이블 (products, materials 등)
     * @param  array  $fieldValues  [field_id => value] 형태
     * @param  int|null  $recordId  수정 시 레코드 ID
     * @return array 저장된 데이터
     */
    public function saveData(string $sourceTable, array $fieldValues, ?int $recordId = null): array
    {
        // 해당 테이블의 필드 매핑 정보 조회
        $fields = ItemField::where('tenant_id', $this->tenantId())
            ->where('source_table', $sourceTable)
            ->get()
            ->keyBy('id');

        $columnData = [];  // DB 컬럼 직접 저장
        $jsonData = [];    // JSON (attributes/options) 저장

        foreach ($fieldValues as $fieldId => $value) {
            $field = $fields->get($fieldId);

            if (! $field) {
                // 시스템 필드가 아닌 커스텀 필드
                $customField = ItemField::find($fieldId);
                if ($customField) {
                    $jsonPath = $customField->json_path ?? "attributes.{$customField->field_key}";
                    data_set($jsonData, $jsonPath, $value);
                }

                continue;
            }

            if ($field->isColumnStorage()) {
                // DB 컬럼에 직접 저장
                $columnData[$field->source_column] = $this->castValue($value, $field);
            } else {
                // JSON 필드에 저장
                $jsonPath = $field->json_path ?? "attributes.{$field->field_key}";
                data_set($jsonData, $jsonPath, $value);
            }
        }

        // JSON 데이터 병합
        if (! empty($jsonData['attributes'])) {
            $columnData['attributes'] = json_encode($jsonData['attributes']);
        }
        if (! empty($jsonData['options'])) {
            $columnData['options'] = json_encode($jsonData['options']);
        }

        // 공통 컬럼 추가
        $columnData['tenant_id'] = $this->tenantId();
        $columnData['updated_by'] = $this->apiUserId();

        if ($recordId) {
            // 수정
            DB::table($sourceTable)
                ->where('tenant_id', $this->tenantId())
                ->where('id', $recordId)
                ->update($columnData);

            return array_merge(['id' => $recordId], $columnData);
        } else {
            // 생성
            $columnData['created_by'] = $this->apiUserId();
            $id = DB::table($sourceTable)->insertGetId($columnData);

            return array_merge(['id' => $id], $columnData);
        }
    }

    /**
     * 필드 타입에 따른 값 변환
     */
    private function castValue($value, ItemField $field)
    {
        return match ($field->field_type) {
            'number' => is_numeric($value) ? (float) $value : null,
            'checkbox' => filter_var($value, FILTER_VALIDATE_BOOLEAN),
            'date' => $value ? date('Y-m-d', strtotime($value)) : null,
            default => $value,
        };
    }

    /**
     * 레코드 조회 시 필드 매핑 적용
     *
     * @param  string  $sourceTable  대상 테이블 (products, materials 등)
     * @param  int  $recordId  레코드 ID
     * @return array 필드 ID => 값 형태의 데이터
     */
    public function getData(string $sourceTable, int $recordId): array
    {
        $record = DB::table($sourceTable)
            ->where('tenant_id', $this->tenantId())
            ->where('id', $recordId)
            ->first();

        if (! $record) {
            return [];
        }

        // 필드 매핑 정보 조회
        $fields = ItemField::where('tenant_id', $this->tenantId())
            ->where('source_table', $sourceTable)
            ->get();

        $result = [];
        $attributes = json_decode($record->attributes ?? '{}', true);
        $options = json_decode($record->options ?? '{}', true);

        foreach ($fields as $field) {
            if ($field->isColumnStorage()) {
                $result[$field->id] = $record->{$field->source_column} ?? null;
            } else {
                $jsonPath = $field->json_path ?? "attributes.{$field->field_key}";
                $result[$field->id] = data_get(
                    ['attributes' => $attributes, 'options' => $options],
                    $jsonPath
                );
            }
        }

        return $result;
    }

    /**
     * 페이지 기반으로 레코드 저장
     *
     * @param  int  $pageId  ItemPage ID
     * @param  array  $fieldValues  [field_id => value] 형태
     * @param  int|null  $recordId  수정 시 레코드 ID
     * @return array 저장된 데이터
     */
    public function saveDataByPage(int $pageId, array $fieldValues, ?int $recordId = null): array
    {
        $page = \App\Models\ItemMaster\ItemPage::find($pageId);

        if (! $page || ! $page->source_table) {
            throw new \InvalidArgumentException("Invalid page or source_table not defined for page: {$pageId}");
        }

        return $this->saveData($page->source_table, $fieldValues, $recordId);
    }

    /**
     * 페이지 기반으로 레코드 조회
     *
     * @param  int  $pageId  ItemPage ID
     * @param  int  $recordId  레코드 ID
     * @return array 필드 ID => 값 형태의 데이터
     */
    public function getDataByPage(int $pageId, int $recordId): array
    {
        $page = \App\Models\ItemMaster\ItemPage::find($pageId);

        if (! $page || ! $page->source_table) {
            throw new \InvalidArgumentException("Invalid page or source_table not defined for page: {$pageId}");
        }

        return $this->getData($page->source_table, $recordId);
    }
}
