<?php

namespace App\Services;

use App\Models\Boards\Board;
use App\Models\Boards\BoardSetting;
use App\Models\Tenants\Tenant;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\DB;

class BoardService
{
    public function __construct(
        protected MenuService $menuService
    ) {}

    /**
     * 시스템 게시판 목록 조회 (페이지네이션)
     */
    public function getBoards(array $filters = [], int $perPage = 15): LengthAwarePaginator
    {
        $query = Board::query()
            ->systemOnly()
            ->withCount('fields')
            ->withTrashed();

        // 검색 필터
        if (! empty($filters['search'])) {
            $search = $filters['search'];
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                    ->orWhere('board_code', 'like', "%{$search}%")
                    ->orWhere('description', 'like', "%{$search}%");
            });
        }

        // 게시판 유형 필터
        if (! empty($filters['board_type'])) {
            $query->where('board_type', $filters['board_type']);
        }

        // 활성 상태 필터
        if (isset($filters['is_active']) && $filters['is_active'] !== '') {
            $query->where('is_active', $filters['is_active']);
        }

        // Soft Delete 필터
        if (isset($filters['trashed'])) {
            if ($filters['trashed'] === 'only') {
                $query->onlyTrashed();
            } elseif ($filters['trashed'] === 'with') {
                $query->withTrashed();
            }
        }

        // 정렬
        $sortBy = $filters['sort_by'] ?? 'id';
        $sortDirection = $filters['sort_direction'] ?? 'desc';
        $query->orderBy($sortBy, $sortDirection);

        return $query->paginate($perPage);
    }

    /**
     * 시스템 게시판 목록 (드롭다운용)
     */
    public function getActiveBoardList(): Collection
    {
        return Board::query()
            ->systemOnly()
            ->active()
            ->orderBy('name')
            ->get(['id', 'board_code', 'name', 'board_type']);
    }

    /**
     * 특정 게시판 조회
     *
     * @param  bool  $systemOnly  true면 시스템 게시판만, false면 모든 게시판
     */
    public function getBoardById(int $id, bool $withTrashed = false, bool $systemOnly = true): ?Board
    {
        $query = Board::query()
            ->with(['fields', 'tenant:id,code,company_name'])
            ->withCount('fields');

        if ($systemOnly) {
            $query->systemOnly();
        }

        if ($withTrashed) {
            $query->withTrashed();
        }

        return $query->find($id);
    }

    /**
     * 게시판 생성
     */
    public function createBoard(array $data): Board
    {
        // 시스템 게시판 설정
        $data['is_system'] = true;
        $data['tenant_id'] = null;
        $data['created_by'] = auth()->id();

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

        // 메뉴 자동 생성
        $this->menuService->createMenuForBoard([
            'board_code' => $board->board_code,
            'name' => $board->name,
            'is_system' => true,
            'tenant_id' => null,
        ]);

        return $board;
    }

    /**
     * 게시판 수정
     */
    public function updateBoard(int $id, array $data): bool
    {
        $board = Board::systemOnly()->findOrFail($id);

        $data['updated_by'] = auth()->id();

        return $board->update($data);
    }

    /**
     * 게시판 삭제 (Soft Delete)
     */
    public function deleteBoard(int $id): bool
    {
        $board = Board::systemOnly()->findOrFail($id);

        $board->deleted_by = auth()->id();
        $board->save();

        return $board->delete();
    }

    /**
     * 게시판 복원
     */
    public function restoreBoard(int $id): bool
    {
        $board = Board::systemOnly()->onlyTrashed()->findOrFail($id);

        $board->deleted_by = null;

        return $board->restore();
    }

    /**
     * 게시판 영구 삭제
     */
    public function forceDeleteBoard(int $id): bool
    {
        $board = Board::systemOnly()->withTrashed()->findOrFail($id);

        // 관련 필드 삭제
        $board->fields()->delete();

        return $board->forceDelete();
    }

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

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

        return $query->exists();
    }

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

        $board->is_active = ! $board->is_active;
        $board->updated_by = auth()->id();
        $board->save();

        return $board;
    }

    /**
     * 게시판 통계
     */
    public function getBoardStats(): array
    {
        return [
            'total' => Board::systemOnly()->count(),
            'active' => Board::systemOnly()->active()->count(),
            'inactive' => Board::systemOnly()->where('is_active', false)->count(),
            'trashed' => Board::systemOnly()->onlyTrashed()->count(),
        ];
    }

    // =========================================================================
    // 필드 관리
    // =========================================================================

    /**
     * 게시판 필드 목록 조회
     */
    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'] = auth()->id();

        // 기본 정렬 순서 설정
        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): bool
    {
        $field = BoardSetting::findOrFail($fieldId);

        $data['updated_by'] = auth()->id();

        return $field->update($data);
    }

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

        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 getBoardTypes(): array
    {
        return Board::systemOnly()
            ->whereNotNull('board_type')
            ->distinct()
            ->pluck('board_type')
            ->toArray();
    }

    // =========================================================================
    // 템플릿 관리
    // =========================================================================

    /**
     * 템플릿 목록 조회
     */
    public function getTemplates(string $type = 'all'): array
    {
        $templates = config('board_templates', []);

        if ($type === 'system') {
            return $templates['system'] ?? [];
        }

        if ($type === 'tenant') {
            return $templates['tenant'] ?? [];
        }

        return [
            'system' => $templates['system'] ?? [],
            'tenant' => $templates['tenant'] ?? [],
        ];
    }

    /**
     * 특정 템플릿 조회
     */
    public function getTemplate(string $type, string $key): ?array
    {
        $templates = $this->getTemplates($type);

        return $templates[$key] ?? null;
    }

    /**
     * 기본 필드 목록 조회
     */
    public function getBaseFields(): array
    {
        return config('board_templates.base_fields', []);
    }

    /**
     * 템플릿 기반 게시판 생성
     *
     * @param  bool  $createMenu  메뉴 자동 생성 여부 (기본: true)
     */
    public function createBoardFromTemplate(array $data, ?string $templateType = null, ?string $templateKey = null, bool $createMenu = true): Board
    {
        return DB::transaction(function () use ($data, $templateType, $templateKey, $createMenu) {
            // 템플릿 설정 적용
            $template = null;
            if ($templateType && $templateKey) {
                $template = $this->getTemplate($templateType, $templateKey);
                if ($template) {
                    // 템플릿 기본값 적용 (사용자 입력값 우선)
                    $data = array_merge([
                        'board_type' => $template['board_type'] ?? null,
                        'editor_type' => $template['editor_type'] ?? 'wysiwyg',
                        'allow_files' => $template['allow_files'] ?? true,
                        'max_file_count' => $template['max_file_count'] ?? 5,
                        'max_file_size' => $template['max_file_size'] ?? 20480,
                        'extra_settings' => $template['extra_settings'] ?? [],
                    ], $data);
                }
            }

            // 시스템/테넌트 구분
            if (isset($data['tenant_id']) && $data['tenant_id']) {
                // 테넌트 게시판
                $data['is_system'] = false;
            } else {
                // 시스템 게시판
                $data['is_system'] = true;
                $data['tenant_id'] = null;
            }

            $data['created_by'] = auth()->id();

            // 게시판 생성
            $board = Board::create($data);

            // 템플릿 기본 필드 생성
            if ($template && ! empty($template['default_fields'])) {
                foreach ($template['default_fields'] as $index => $field) {
                    $field['board_id'] = $board->id;
                    $field['sort_order'] = $index + 1;
                    $field['created_by'] = auth()->id();
                    BoardSetting::create($field);
                }
            }

            // 메뉴 자동 생성
            if ($createMenu) {
                $this->menuService->createMenuForBoard([
                    'board_code' => $board->board_code,
                    'name' => $board->name,
                    'is_system' => $board->is_system,
                    'tenant_id' => $board->tenant_id,
                ]);
            }

            return $board->load('fields');
        });
    }

    // =========================================================================
    // 테넌트 게시판 관리
    // =========================================================================

    /**
     * 모든 게시판 목록 조회 (시스템 + 테넌트)
     */
    public function getAllBoards(array $filters = [], int $perPage = 15): LengthAwarePaginator
    {
        $query = Board::query()
            ->with('tenant:id,code,company_name')
            ->withCount(['fields', 'posts'])
            ->withTrashed();

        // 헤더에서 선택한 테넌트 기준
        $selectedTenantId = session('selected_tenant_id');

        if ($selectedTenantId && $selectedTenantId !== 'all') {
            // 선택된 테넌트가 본사(HQ)인지 확인
            $isHQ = Tenant::where('id', $selectedTenantId)
                ->where('tenant_type', 'HQ')
                ->exists();

            if ($isHQ) {
                // 본사: 시스템 게시판 + 본사 테넌트 게시판
                $query->where(function ($q) use ($selectedTenantId) {
                    $q->where('is_system', true)
                        ->orWhere('tenant_id', $selectedTenantId);
                });
            } else {
                // 일반 테넌트: 해당 테넌트 게시판만 (시스템 게시판 제외)
                $query->where('tenant_id', $selectedTenantId);
            }
        } else {
            // 전체 보기: 시스템 게시판만 (테넌트 게시판은 테넌트 선택 후 표시)
            $query->where('is_system', true);
        }

        // 검색 필터
        if (! empty($filters['search'])) {
            $search = $filters['search'];
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                    ->orWhere('board_code', 'like', "%{$search}%")
                    ->orWhere('description', 'like', "%{$search}%");
            });
        }

        // 게시판 유형 필터
        if (! empty($filters['board_type'])) {
            $query->where('board_type', $filters['board_type']);
        }

        // 활성 상태 필터
        if (isset($filters['is_active']) && $filters['is_active'] !== '') {
            $query->where('is_active', $filters['is_active']);
        }

        // Soft Delete 필터
        if (isset($filters['trashed'])) {
            if ($filters['trashed'] === 'only') {
                $query->onlyTrashed();
            } elseif ($filters['trashed'] === 'with') {
                $query->withTrashed();
            }
        }

        // 정렬: 시스템 게시판 우선, 그 다음 사용자 지정 정렬
        $sortBy = $filters['sort_by'] ?? 'id';
        $sortDirection = $filters['sort_direction'] ?? 'desc';
        $query->orderBy('is_system', 'desc')  // 시스템 게시판 우선
            ->orderBy($sortBy, $sortDirection);

        return $query->paginate($perPage);
    }

    /**
     * 테넌트 목록 조회 (드롭다운용)
     */
    public function getTenantList(): Collection
    {
        return Tenant::query()
            ->active()
            ->orderBy('company_name')
            ->get(['id', 'code', 'company_name']);
    }

    /**
     * 테넌트 게시판 코드 중복 체크
     */
    public function isTenantCodeExists(string $code, int $tenantId, ?int $excludeId = null): bool
    {
        $query = Board::where('board_code', $code)
            ->where('tenant_id', $tenantId);

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

        return $query->exists();
    }

    /**
     * 게시판 상세 조회 (시스템/테넌트 공통)
     */
    public function getAnyBoardById(int $id, bool $withTrashed = false): ?Board
    {
        $query = Board::query()
            ->with('fields')
            ->withCount('fields');

        if ($withTrashed) {
            $query->withTrashed();
        }

        return $query->find($id);
    }

    /**
     * 게시판 수정 (시스템/테넌트 공통)
     */
    public function updateAnyBoard(int $id, array $data): bool
    {
        $board = Board::findOrFail($id);

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

        $data['updated_by'] = auth()->id();

        // tenant_id 변경 방지 (시스템 ↔ 테넌트 전환 불가)
        unset($data['tenant_id'], $data['is_system']);

        $result = $board->update($data);

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

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

        return $result;
    }

    /**
     * 게시판 삭제 (시스템/테넌트 공통, Soft Delete)
     * - 연결된 메뉴도 함께 Soft Delete
     */
    public function deleteAnyBoard(int $id): bool
    {
        $board = Board::findOrFail($id);

        $board->deleted_by = auth()->id();
        $board->save();

        // 연결된 메뉴도 함께 삭제 (Soft Delete)
        $this->menuService->deleteMenuForBoard(
            $board->board_code,
            $board->is_system,
            $board->tenant_id
        );

        return $board->delete();
    }

    /**
     * 게시판 복원 (시스템/테넌트 공통)
     * - 연결된 메뉴도 함께 복원
     */
    public function restoreAnyBoard(int $id): bool
    {
        $board = Board::onlyTrashed()->findOrFail($id);

        $board->deleted_by = null;

        // 게시판 복원
        $result = $board->restore();

        // 연결된 메뉴도 복원 (없으면 생성)
        if ($result) {
            $this->menuService->restoreMenuForBoard(
                $board->board_code,
                $board->name,
                $board->is_system,
                $board->tenant_id
            );
        }

        return $result;
    }

    /**
     * 게시판 영구 삭제 (시스템/테넌트 공통)
     * - 연결된 메뉴도 함께 영구 삭제
     */
    public function forceDeleteAnyBoard(int $id): bool
    {
        $board = Board::withTrashed()->findOrFail($id);

        // 관련 필드 삭제
        $board->fields()->delete();

        // 연결된 메뉴도 함께 영구 삭제
        $this->menuService->deleteMenuForBoard(
            $board->board_code,
            $board->is_system,
            $board->tenant_id,
            true // forceDelete
        );

        return $board->forceDelete();
    }
}
