<?php

namespace App\Services\Boards;

use App\Models\Boards\Board;
use App\Models\Boards\BoardSetting;
use App\Services\MenuService;
use App\Services\Service;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Collection;

class BoardService extends Service
{
    // =========================================================================
    // 조회 메서드
    // =========================================================================

    /**
     * 접근 가능한 게시판 목록 (시스템 + 테넌트)
     */
    public function getAccessibleBoards(array $filters = []): Collection
    {
        return Board::accessible($this->tenantId())
            ->when(isset($filters['board_type']), fn ($q) => $q->where('board_type', $filters['board_type']))
            ->when(isset($filters['search']), fn ($q) => $q->where('name', 'like', "%{$filters['search']}%"))
            ->orderBy('is_system', 'desc')
            ->orderBy('name')
            ->get();
    }

    /**
     * 시스템 게시판 목록 (mng용)
     */
    public function getSystemBoards(array $filters = []): Collection
    {
        return Board::systemOnly()
            ->when(isset($filters['board_type']), fn ($q) => $q->where('board_type', $filters['board_type']))
            ->when(isset($filters['search']), fn ($q) => $q->where('name', 'like', "%{$filters['search']}%"))
            ->orderBy('name')
            ->get();
    }

    /**
     * 시스템 게시판 페이징 목록 (mng용)
     */
    public function getSystemBoardsPaginated(array $filters = [], int $perPage = 15): LengthAwarePaginator
    {
        return Board::systemOnly()
            ->when(isset($filters['board_type']), fn ($q) => $q->where('board_type', $filters['board_type']))
            ->when(isset($filters['search']), fn ($q) => $q->where('name', 'like', "%{$filters['search']}%"))
            ->when(isset($filters['is_active']), fn ($q) => $q->where('is_active', $filters['is_active']))
            ->orderBy('name')
            ->paginate($perPage);
    }

    /**
     * 테넌트 게시판만 가져오기
     */
    public function getTenantBoards(array $filters = []): Collection
    {
        return Board::tenantOnly($this->tenantId())
            ->when(isset($filters['board_type']), fn ($q) => $q->where('board_type', $filters['board_type']))
            ->when(isset($filters['search']), fn ($q) => $q->where('name', 'like', "%{$filters['search']}%"))
            ->orderBy('name')
            ->get();
    }

    /**
     * 게시판 코드로 조회 (접근 가능한 게시판 중에서)
     */
    public function getBoardByCode(string $code): ?Board
    {
        return Board::accessible($this->tenantId())
            ->where('board_code', $code)
            ->first();
    }

    /**
     * 시스템 게시판 코드로 조회
     */
    public function getSystemBoardByCode(string $code): ?Board
    {
        return Board::systemOnly()
            ->where('board_code', $code)
            ->where('is_active', true)
            ->first();
    }

    /**
     * 테넌트 게시판 코드로 조회
     */
    public function getTenantBoardByCode(string $code): ?Board
    {
        return Board::tenantOnly($this->tenantId())
            ->where('board_code', $code)
            ->where('is_active', true)
            ->first();
    }

    /**
     * 시스템 게시판 ID로 조회 (mng용)
     */
    public function getSystemBoardById(int $id): ?Board
    {
        return Board::systemOnly()
            ->with('customFields')
            ->find($id);
    }

    /**
     * 게시판 ID로 조회 (상세)
     */
    public function getBoardDetail(int $id): ?Board
    {
        return Board::with('customFields')
            ->find($id);
    }

    // =========================================================================
    // 생성 메서드
    // =========================================================================

    /**
     * 시스템 게시판 생성 (mng용)
     */
    public function createSystemBoard(array $data): Board
    {
        $data['is_system'] = true;
        $data['tenant_id'] = null;
        $data['created_by'] = $this->apiUserId();

        return Board::create($data);
    }

    /**
     * 테넌트 게시판 생성 (sam용)
     * - 게시판 생성 후 메뉴 자동 생성
     */
    public function createTenantBoard(array $data): Board
    {
        $data['is_system'] = false;
        $data['tenant_id'] = $this->tenantId();
        $data['created_by'] = $this->apiUserId();

        $board = Board::create($data);

        // 메뉴 자동 생성
        MenuService::createMenuForBoard(
            $board->board_code,
            $board->name,
            $board->tenant_id
        );

        return $board;
    }

    // =========================================================================
    // 수정 메서드
    // =========================================================================

    /**
     * 시스템 게시판 수정 (mng용)
     */
    public function updateSystemBoard(int $id, array $data): ?Board
    {
        $board = Board::systemOnly()->find($id);

        if (! $board) {
            return null;
        }

        $data['updated_by'] = $this->apiUserId();
        $board->update($data);

        return $board->fresh();
    }

    /**
     * 테넌트 게시판 수정 (sam용)
     * - 코드/이름 변경 시 메뉴도 자동 수정
     */
    public function updateTenantBoard(int $id, array $data): ?Board
    {
        $board = Board::tenantOnly($this->tenantId())->find($id);

        if (! $board) {
            return null;
        }

        // 기존 코드/이름 저장 (메뉴 업데이트용)
        $oldCode = $board->board_code;
        $oldName = $board->name;

        $data['updated_by'] = $this->apiUserId();
        $board->update($data);

        // 코드 또는 이름 변경 시 메뉴도 업데이트
        $newCode = $data['board_code'] ?? $oldCode;
        $newName = $data['name'] ?? $oldName;

        if ($oldCode !== $newCode || $oldName !== $newName) {
            MenuService::updateMenuForBoard(
                $oldCode,
                $newCode,
                $newName,
                $board->tenant_id
            );
        }

        return $board->fresh();
    }

    // =========================================================================
    // 삭제 메서드
    // =========================================================================

    /**
     * 시스템 게시판 삭제 (mng용)
     */
    public function deleteSystemBoard(int $id): bool
    {
        $board = Board::systemOnly()->find($id);

        if (! $board) {
            return false;
        }

        $board->deleted_by = $this->apiUserId();
        $board->save();
        $board->delete();

        return true;
    }

    /**
     * 테넌트 게시판 삭제 (sam용)
     * - 게시판 삭제 시 메뉴도 자동 삭제 (Soft Delete)
     */
    public function deleteTenantBoard(int $id): bool
    {
        $board = Board::tenantOnly($this->tenantId())->find($id);

        if (! $board) {
            return false;
        }

        $boardCode = $board->board_code;
        $tenantId = $board->tenant_id;

        $board->deleted_by = $this->apiUserId();
        $board->save();
        $board->delete();

        // 메뉴도 함께 삭제 (Soft Delete)
        MenuService::deleteMenuForBoard($boardCode, $tenantId);

        return true;
    }

    // =========================================================================
    // 필드 관리 메서드
    // =========================================================================

    /**
     * 게시판 필드 목록 조회
     */
    public function getBoardFields(int $boardId): Collection
    {
        return BoardSetting::where('board_id', $boardId)
            ->orderBy('sort_order')
            ->get();
    }

    /**
     * 게시판 필드 추가
     */
    public function addBoardField(int $boardId, array $data): BoardSetting
    {
        $data['board_id'] = $boardId;
        $data['created_by'] = $this->apiUserId();

        // 기본 정렬 순서 설정
        if (! isset($data['sort_order'])) {
            $maxOrder = BoardSetting::where('board_id', $boardId)->max('sort_order') ?? 0;
            $data['sort_order'] = $maxOrder + 1;
        }

        return BoardSetting::create($data);
    }

    /**
     * 게시판 필드 수정
     */
    public function updateBoardField(int $fieldId, array $data): ?BoardSetting
    {
        $field = BoardSetting::find($fieldId);

        if (! $field) {
            return null;
        }

        $data['updated_by'] = $this->apiUserId();
        $field->update($data);

        return $field->fresh();
    }

    /**
     * 게시판 필드 삭제
     */
    public function deleteBoardField(int $fieldId): bool
    {
        $field = BoardSetting::find($fieldId);

        if (! $field) {
            return false;
        }

        return $field->delete();
    }

    /**
     * 게시판 필드 순서 변경
     */
    public function reorderBoardFields(int $boardId, array $fieldIds): bool
    {
        foreach ($fieldIds as $order => $fieldId) {
            BoardSetting::where('id', $fieldId)
                ->where('board_id', $boardId)
                ->update(['sort_order' => $order + 1]);
        }

        return true;
    }

    // =========================================================================
    // 유틸리티 메서드
    // =========================================================================

    /**
     * 게시판 코드 중복 확인
     */
    public function isCodeExists(string $code, ?int $excludeId = null): bool
    {
        $query = Board::where('board_code', $code);

        // 시스템 게시판이면 시스템 게시판 중에서 확인
        // 테넌트 게시판이면 해당 테넌트 중에서 확인
        $query->where(function ($q) {
            $q->where('is_system', true)
                ->orWhere('tenant_id', $this->tenantIdOrNull());
        });

        if ($excludeId) {
            $query->where('id', '!=', $excludeId);
        }

        return $query->exists();
    }

    /**
     * 게시판 활성/비활성 토글
     */
    public function toggleActive(int $id): ?Board
    {
        $board = Board::find($id);

        if (! $board) {
            return null;
        }

        $board->is_active = ! $board->is_active;
        $board->updated_by = $this->apiUserId();
        $board->save();

        return $board;
    }
}
