<?php

namespace App\Services\ItemMaster;

use App\Models\ItemMaster\EntityRelationship;
use App\Models\ItemMaster\ItemSection;
use App\Services\Service;
use App\Traits\LockCheckTrait;
use Illuminate\Database\Eloquent\Collection;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class ItemSectionService extends Service
{
    use LockCheckTrait;

    /**
     * 모든 섹션 목록 조회
     *
     * GET /api/v1/item-master/sections
     */
    public function index(?bool $isTemplate = null): Collection
    {
        $tenantId = $this->tenantId();

        $query = ItemSection::where('tenant_id', $tenantId);

        if ($isTemplate === true) {
            $query->templates();
        } elseif ($isTemplate === false) {
            $query->nonTemplates();
        }

        return $query->orderBy('created_at', 'desc')->get();
    }

    /**
     * 독립 섹션 생성 (페이지 연결 없음)
     *
     * POST /api/v1/item-master/sections
     */
    public function storeIndependent(array $data): ItemSection
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        $section = ItemSection::create([
            'tenant_id' => $tenantId,
            'group_id' => $data['group_id'] ?? 1,
            'title' => $data['title'],
            'type' => $data['type'],
            'order_no' => 0,
            'is_template' => $data['is_template'] ?? false,
            'is_default' => $data['is_default'] ?? false,
            'description' => $data['description'] ?? null,
            'created_by' => $userId,
        ]);

        return $section->loadRelatedEntities();
    }

    /**
     * 섹션 복제
     *
     * POST /api/v1/item-master/sections/{id}/clone
     */
    public function clone(int $id): ItemSection
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        $original = ItemSection::where('tenant_id', $tenantId)
            ->where('id', $id)
            ->first();

        if (! $original) {
            throw new NotFoundHttpException(__('error.section_not_found'));
        }

        // 원본 섹션의 관련 엔티티 로드 (entity_relationships 기반)
        $original->loadRelatedEntities();

        // 섹션 복제
        $cloned = ItemSection::create([
            'tenant_id' => $tenantId,
            'group_id' => $original->group_id,
            'title' => $original->title.' (복사본)',
            'type' => $original->type,
            'order_no' => 0,
            'is_template' => $original->is_template,
            'is_default' => false,
            'description' => $original->description,
            'created_by' => $userId,
        ]);

        // 기존 필드에 대한 링크만 생성 (필드는 복제하지 않음 - 링크 관계)
        foreach ($original->getRelation('fields') as $orderNo => $field) {
            EntityRelationship::link(
                $tenantId,
                EntityRelationship::TYPE_SECTION,
                $cloned->id,
                EntityRelationship::TYPE_FIELD,
                $field->id,
                $field->order_no,
                null,
                $field->group_id
            );
        }

        // 기존 BOM에 대한 링크만 생성 (BOM은 복제하지 않음 - 링크 관계)
        foreach ($original->getRelation('bomItems') as $orderNo => $bom) {
            EntityRelationship::link(
                $tenantId,
                EntityRelationship::TYPE_SECTION,
                $cloned->id,
                EntityRelationship::TYPE_BOM,
                $bom->id,
                $orderNo,
                null,
                $bom->group_id
            );
        }

        return $cloned->loadRelatedEntities();
    }

    /**
     * 섹션 사용처 조회 (어떤 페이지에 연결되어 있는지)
     *
     * GET /api/v1/item-master/sections/{id}/usage
     */
    public function getUsage(int $id): array
    {
        $tenantId = $this->tenantId();

        $section = ItemSection::where('tenant_id', $tenantId)
            ->where('id', $id)
            ->first();

        if (! $section) {
            throw new NotFoundHttpException(__('error.section_not_found'));
        }

        // entity_relationships 기반 연결
        $linkedPages = $section->linkedPages()->get();

        return [
            'section_id' => $id,
            'linked_pages' => $linkedPages,
            'total_usage_count' => $linkedPages->count(),
        ];
    }

    /**
     * 섹션 생성 및 페이지에 연결
     */
    public function store(int $pageId, array $data): ItemSection
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        // order_no 자동 계산 (해당 페이지에 연결된 마지막 섹션 + 1)
        $maxOrder = EntityRelationship::where('parent_type', EntityRelationship::TYPE_PAGE)
            ->where('parent_id', $pageId)
            ->where('child_type', EntityRelationship::TYPE_SECTION)
            ->max('order_no');

        // 섹션 생성
        $section = ItemSection::create([
            'tenant_id' => $tenantId,
            'group_id' => $data['group_id'] ?? 1,
            'title' => $data['title'],
            'type' => $data['type'],
            'order_no' => ($maxOrder ?? -1) + 1,
            'created_by' => $userId,
        ]);

        // 페이지-섹션 관계 생성
        EntityRelationship::link(
            $tenantId,
            EntityRelationship::TYPE_PAGE,
            $pageId,
            EntityRelationship::TYPE_SECTION,
            $section->id,
            ($maxOrder ?? -1) + 1,
            null,
            $data['group_id'] ?? 1
        );

        $section->loadRelatedEntities();

        return $section;
    }

    /**
     * 섹션 수정
     */
    public function update(int $id, array $data): ItemSection
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        $section = ItemSection::where('tenant_id', $tenantId)
            ->where('id', $id)
            ->first();

        if (! $section) {
            throw new NotFoundHttpException(__('error.not_found'));
        }

        $section->update([
            'title' => $data['title'] ?? $section->title,
            'updated_by' => $userId,
        ]);

        $section->loadRelatedEntities();

        return $section;
    }

    /**
     * 섹션 삭제 (Soft Delete)
     *
     * 독립 엔티티 아키텍처: 섹션만 삭제하고 연결된 필드/BOM은 unlink만 수행
     *
     * @throws \App\Exceptions\BusinessException 잠금된 연결이 있는 경우
     */
    public function destroy(int $id): void
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        $section = ItemSection::where('tenant_id', $tenantId)
            ->where('id', $id)
            ->first();

        if (! $section) {
            throw new NotFoundHttpException(__('error.not_found'));
        }

        // 잠금 체크: 이 섹션이 잠금된 연결로 보호되고 있는지 확인
        $this->checkCanDelete(EntityRelationship::TYPE_SECTION, $id);

        // 1. entity_relationships에서 이 섹션의 모든 부모 관계 해제
        //    (page→section 관계에서 이 섹션 제거)
        //    주의: 잠금된 연결이 있으면 예외 발생
        EntityRelationship::where('child_type', EntityRelationship::TYPE_SECTION)
            ->where('child_id', $id)
            ->where('is_locked', false)
            ->delete();

        // 2. entity_relationships에서 이 섹션의 모든 자식 관계 해제
        //    (section→field, section→bom 관계 삭제)
        //    주의: 잠금된 연결이 있으면 예외 발생 (unlinkAllChildren에서 처리)
        EntityRelationship::unlinkAllChildren(
            $tenantId,
            EntityRelationship::TYPE_SECTION,
            $id
        );

        // 3. 섹션만 Soft Delete (필드/BOM은 독립 엔티티로 유지)
        $section->update(['deleted_by' => $userId]);
        $section->delete();
    }

    /**
     * 섹션 순서 변경 (entity_relationships 기반)
     *
     * @param  array  $items  [['id' => 1, 'order_no' => 0], ['id' => 2, 'order_no' => 1], ...]
     */
    public function reorder(int $pageId, array $items): void
    {
        foreach ($items as $item) {
            // entity_relationships에서 순서 업데이트
            EntityRelationship::where('parent_type', EntityRelationship::TYPE_PAGE)
                ->where('parent_id', $pageId)
                ->where('child_type', EntityRelationship::TYPE_SECTION)
                ->where('child_id', $item['id'])
                ->update(['order_no' => $item['order_no']]);

            // 섹션 자체의 order_no도 동기화
            ItemSection::where('id', $item['id'])
                ->update(['order_no' => $item['order_no']]);
        }
    }
}
