<?php

namespace App\Services\ItemMaster;

use App\Models\ItemMaster\EntityRelationship;
use App\Models\ItemMaster\ItemBomItem;
use App\Models\ItemMaster\ItemField;
use App\Models\ItemMaster\ItemPage;
use App\Models\ItemMaster\ItemSection;
use App\Services\Service;
use Illuminate\Support\Collection;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * EntityRelationshipService - 엔티티 간 관계(링크) 관리 서비스
 */
class EntityRelationshipService extends Service
{
    /**
     * 페이지에 섹션 연결
     */
    public function linkSectionToPage(int $pageId, int $sectionId, int $orderNo = 0): EntityRelationship
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        // 페이지 존재 확인
        $page = ItemPage::where('tenant_id', $tenantId)->find($pageId);
        if (! $page) {
            throw new NotFoundHttpException(__('error.page_not_found'));
        }

        // 섹션 존재 확인
        $section = ItemSection::where('tenant_id', $tenantId)->find($sectionId);
        if (! $section) {
            throw new NotFoundHttpException(__('error.section_not_found'));
        }

        return EntityRelationship::link(
            $tenantId,
            EntityRelationship::TYPE_PAGE,
            $pageId,
            EntityRelationship::TYPE_SECTION,
            $sectionId,
            $orderNo
        );
    }

    /**
     * 페이지에서 섹션 연결 해제
     */
    public function unlinkSectionFromPage(int $pageId, int $sectionId): bool
    {
        $tenantId = $this->tenantId();

        return EntityRelationship::unlink(
            $tenantId,
            EntityRelationship::TYPE_PAGE,
            $pageId,
            EntityRelationship::TYPE_SECTION,
            $sectionId
        );
    }

    /**
     * 페이지에 필드 직접 연결
     */
    public function linkFieldToPage(int $pageId, int $fieldId, int $orderNo = 0): EntityRelationship
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        // 페이지 존재 확인
        $page = ItemPage::where('tenant_id', $tenantId)->find($pageId);
        if (! $page) {
            throw new NotFoundHttpException(__('error.page_not_found'));
        }

        // 필드 존재 확인
        $field = ItemField::where('tenant_id', $tenantId)->find($fieldId);
        if (! $field) {
            throw new NotFoundHttpException(__('error.field_not_found'));
        }

        return EntityRelationship::link(
            $tenantId,
            EntityRelationship::TYPE_PAGE,
            $pageId,
            EntityRelationship::TYPE_FIELD,
            $fieldId,
            $orderNo
        );
    }

    /**
     * 페이지에서 필드 연결 해제
     */
    public function unlinkFieldFromPage(int $pageId, int $fieldId): bool
    {
        $tenantId = $this->tenantId();

        return EntityRelationship::unlink(
            $tenantId,
            EntityRelationship::TYPE_PAGE,
            $pageId,
            EntityRelationship::TYPE_FIELD,
            $fieldId
        );
    }

    /**
     * 섹션에 필드 연결
     */
    public function linkFieldToSection(int $sectionId, int $fieldId, int $orderNo = 0): EntityRelationship
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        // 섹션 존재 확인
        $section = ItemSection::where('tenant_id', $tenantId)->find($sectionId);
        if (! $section) {
            throw new NotFoundHttpException(__('error.section_not_found'));
        }

        // 필드 존재 확인
        $field = ItemField::where('tenant_id', $tenantId)->find($fieldId);
        if (! $field) {
            throw new NotFoundHttpException(__('error.field_not_found'));
        }

        return EntityRelationship::link(
            $tenantId,
            EntityRelationship::TYPE_SECTION,
            $sectionId,
            EntityRelationship::TYPE_FIELD,
            $fieldId,
            $orderNo
        );
    }

    /**
     * 섹션에서 필드 연결 해제
     */
    public function unlinkFieldFromSection(int $sectionId, int $fieldId): bool
    {
        $tenantId = $this->tenantId();

        return EntityRelationship::unlink(
            $tenantId,
            EntityRelationship::TYPE_SECTION,
            $sectionId,
            EntityRelationship::TYPE_FIELD,
            $fieldId
        );
    }

    /**
     * 섹션에 BOM 항목 연결
     */
    public function linkBomToSection(int $sectionId, int $bomId, int $orderNo = 0): EntityRelationship
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        // 섹션 존재 확인
        $section = ItemSection::where('tenant_id', $tenantId)->find($sectionId);
        if (! $section) {
            throw new NotFoundHttpException(__('error.section_not_found'));
        }

        // BOM 항목 존재 확인
        $bom = ItemBomItem::where('tenant_id', $tenantId)->find($bomId);
        if (! $bom) {
            throw new NotFoundHttpException(__('error.bom_not_found'));
        }

        return EntityRelationship::link(
            $tenantId,
            EntityRelationship::TYPE_SECTION,
            $sectionId,
            EntityRelationship::TYPE_BOM,
            $bomId,
            $orderNo
        );
    }

    /**
     * 섹션에서 BOM 항목 연결 해제
     */
    public function unlinkBomFromSection(int $sectionId, int $bomId): bool
    {
        $tenantId = $this->tenantId();

        return EntityRelationship::unlink(
            $tenantId,
            EntityRelationship::TYPE_SECTION,
            $sectionId,
            EntityRelationship::TYPE_BOM,
            $bomId
        );
    }

    /**
     * 페이지의 모든 관계 조회
     */
    public function getPageRelationships(int $pageId): Collection
    {
        $tenantId = $this->tenantId();

        $page = ItemPage::where('tenant_id', $tenantId)->find($pageId);
        if (! $page) {
            throw new NotFoundHttpException(__('error.page_not_found'));
        }

        return EntityRelationship::where('tenant_id', $tenantId)
            ->where('parent_type', EntityRelationship::TYPE_PAGE)
            ->where('parent_id', $pageId)
            ->orderBy('order_no')
            ->get();
    }

    /**
     * 섹션의 모든 자식 관계 조회
     */
    public function getSectionChildRelationships(int $sectionId): Collection
    {
        $tenantId = $this->tenantId();

        $section = ItemSection::where('tenant_id', $tenantId)->find($sectionId);
        if (! $section) {
            throw new NotFoundHttpException(__('error.section_not_found'));
        }

        return EntityRelationship::where('tenant_id', $tenantId)
            ->where('parent_type', EntityRelationship::TYPE_SECTION)
            ->where('parent_id', $sectionId)
            ->orderBy('order_no')
            ->get();
    }

    /**
     * 특정 엔티티가 연결된 부모 목록 조회
     */
    public function getParentRelationships(string $childType, int $childId): Collection
    {
        $tenantId = $this->tenantId();

        return EntityRelationship::where('tenant_id', $tenantId)
            ->where('child_type', $childType)
            ->where('child_id', $childId)
            ->get();
    }

    /**
     * 관계 순서 변경
     */
    public function reorderRelationships(string $parentType, int $parentId, array $orderedChildIds): void
    {
        $tenantId = $this->tenantId();

        foreach ($orderedChildIds as $index => $item) {
            EntityRelationship::where([
                'tenant_id' => $tenantId,
                'parent_type' => $parentType,
                'parent_id' => $parentId,
                'child_type' => $item['child_type'],
                'child_id' => $item['child_id'],
            ])->update(['order_no' => $index]);
        }
    }

    /**
     * 부모의 모든 자식 관계 일괄 삭제
     */
    public function unlinkAllChildren(string $parentType, int $parentId, ?string $childType = null): int
    {
        $tenantId = $this->tenantId();

        return EntityRelationship::unlinkAllChildren(
            $tenantId,
            $parentType,
            $parentId,
            $childType
        );
    }

    /**
     * 페이지 구조 조회 (섹션 + 직접 연결된 필드 포함)
     */
    public function getPageStructure(int $pageId): array
    {
        $tenantId = $this->tenantId();

        $page = ItemPage::where('tenant_id', $tenantId)->find($pageId);
        if (! $page) {
            throw new NotFoundHttpException(__('error.page_not_found'));
        }

        // 페이지의 모든 관계 조회
        $relationships = EntityRelationship::where('tenant_id', $tenantId)
            ->where('parent_type', EntityRelationship::TYPE_PAGE)
            ->where('parent_id', $pageId)
            ->orderBy('order_no')
            ->get();

        $structure = [
            'page' => $page,
            'sections' => [],
            'direct_fields' => [],
        ];

        foreach ($relationships as $rel) {
            if ($rel->child_type === EntityRelationship::TYPE_SECTION) {
                $section = ItemSection::find($rel->child_id);
                if ($section) {
                    // 섹션의 자식(필드/BOM) 조회
                    $sectionChildren = $this->getSectionChildren($section->id);
                    $structure['sections'][] = [
                        'section' => $section,
                        'order_no' => $rel->order_no,
                        'fields' => $sectionChildren['fields'],
                        'bom_items' => $sectionChildren['bom_items'],
                    ];
                }
            } elseif ($rel->child_type === EntityRelationship::TYPE_FIELD) {
                $field = ItemField::find($rel->child_id);
                if ($field) {
                    $structure['direct_fields'][] = [
                        'field' => $field,
                        'order_no' => $rel->order_no,
                    ];
                }
            }
        }

        return $structure;
    }

    /**
     * 섹션의 자식 엔티티 조회
     */
    private function getSectionChildren(int $sectionId): array
    {
        $tenantId = $this->tenantId();

        $relationships = EntityRelationship::where('tenant_id', $tenantId)
            ->where('parent_type', EntityRelationship::TYPE_SECTION)
            ->where('parent_id', $sectionId)
            ->orderBy('order_no')
            ->get();

        $result = [
            'fields' => [],
            'bom_items' => [],
        ];

        foreach ($relationships as $rel) {
            if ($rel->child_type === EntityRelationship::TYPE_FIELD) {
                $field = ItemField::find($rel->child_id);
                if ($field) {
                    $result['fields'][] = [
                        'field' => $field,
                        'order_no' => $rel->order_no,
                    ];
                }
            } elseif ($rel->child_type === EntityRelationship::TYPE_BOM) {
                $bom = ItemBomItem::find($rel->child_id);
                if ($bom) {
                    $result['bom_items'][] = [
                        'bom_item' => $bom,
                        'order_no' => $rel->order_no,
                    ];
                }
            }
        }

        return $result;
    }
}
