<?php

namespace App\Services\ApiExplorer;

use App\Models\DevTools\ApiBookmark;
use App\Models\DevTools\ApiEnvironment;
use App\Models\DevTools\ApiHistory;
use App\Models\DevTools\ApiTemplate;
use Illuminate\Support\Collection;

/**
 * API Explorer 비즈니스 로직 통합 서비스
 */
class ApiExplorerService
{
    /*
    |--------------------------------------------------------------------------
    | Bookmark Operations
    |--------------------------------------------------------------------------
    */

    /**
     * 즐겨찾기 목록 조회
     */
    public function getBookmarks(int $userId): Collection
    {
        return ApiBookmark::where('user_id', $userId)
            ->ordered()
            ->get();
    }

    /**
     * 즐겨찾기 추가
     */
    public function addBookmark(int $userId, array $data): ApiBookmark
    {
        $maxOrder = ApiBookmark::where('user_id', $userId)->max('display_order') ?? 0;

        return ApiBookmark::create([
            'user_id' => $userId,
            'endpoint' => $data['endpoint'],
            'method' => strtoupper($data['method']),
            'display_name' => $data['display_name'] ?? null,
            'display_order' => $maxOrder + 1,
            'color' => $data['color'] ?? null,
        ]);
    }

    /**
     * 즐겨찾기 제거
     */
    public function removeBookmark(int $bookmarkId): void
    {
        ApiBookmark::where('id', $bookmarkId)->delete();
    }

    /**
     * 즐겨찾기 수정
     */
    public function updateBookmark(int $bookmarkId, array $data): ?ApiBookmark
    {
        $bookmark = ApiBookmark::find($bookmarkId);

        if (! $bookmark) {
            return null;
        }

        if (isset($data['display_name'])) {
            $bookmark->display_name = $data['display_name'];
        }

        $bookmark->save();

        return $bookmark;
    }

    /**
     * 즐겨찾기 순서 변경
     */
    public function reorderBookmarks(int $userId, array $order): void
    {
        foreach ($order as $index => $id) {
            ApiBookmark::where('id', $id)
                ->where('user_id', $userId)
                ->update(['display_order' => $index]);
        }
    }

    /**
     * 즐겨찾기 여부 확인
     */
    public function isBookmarked(int $userId, string $endpoint, string $method): bool
    {
        return ApiBookmark::where('user_id', $userId)
            ->where('endpoint', $endpoint)
            ->where('method', strtoupper($method))
            ->exists();
    }

    /**
     * 즐겨찾기 토글
     */
    public function toggleBookmark(int $userId, array $data): array
    {
        $existing = ApiBookmark::where('user_id', $userId)
            ->where('endpoint', $data['endpoint'])
            ->where('method', strtoupper($data['method']))
            ->first();

        if ($existing) {
            $existing->delete();

            return ['action' => 'removed', 'bookmark' => null];
        }

        $bookmark = $this->addBookmark($userId, $data);

        return ['action' => 'added', 'bookmark' => $bookmark];
    }

    /*
    |--------------------------------------------------------------------------
    | Template Operations
    |--------------------------------------------------------------------------
    */

    /**
     * 템플릿 목록 조회
     */
    public function getTemplates(int $userId, ?string $endpoint = null, ?string $method = null): Collection
    {
        $query = ApiTemplate::where(function ($q) use ($userId) {
            $q->where('user_id', $userId)
                ->orWhere('is_shared', true);
        });

        if ($endpoint) {
            $query->where('endpoint', $endpoint);
        }

        if ($method) {
            $query->where('method', strtoupper($method));
        }

        return $query->orderBy('name')->get();
    }

    /**
     * 템플릿 저장
     */
    public function saveTemplate(int $userId, array $data): ApiTemplate
    {
        return ApiTemplate::create([
            'user_id' => $userId,
            'endpoint' => $data['endpoint'],
            'method' => strtoupper($data['method']),
            'name' => $data['name'],
            'description' => $data['description'] ?? null,
            'headers' => $data['headers'] ?? null,
            'path_params' => $data['path_params'] ?? null,
            'query_params' => $data['query_params'] ?? null,
            'body' => $data['body'] ?? null,
            'is_shared' => $data['is_shared'] ?? false,
        ]);
    }

    /**
     * 템플릿 수정
     */
    public function updateTemplate(int $templateId, array $data): ApiTemplate
    {
        $template = ApiTemplate::findOrFail($templateId);

        $template->update([
            'name' => $data['name'] ?? $template->name,
            'description' => $data['description'] ?? $template->description,
            'headers' => $data['headers'] ?? $template->headers,
            'path_params' => $data['path_params'] ?? $template->path_params,
            'query_params' => $data['query_params'] ?? $template->query_params,
            'body' => $data['body'] ?? $template->body,
            'is_shared' => $data['is_shared'] ?? $template->is_shared,
        ]);

        return $template->fresh();
    }

    /**
     * 템플릿 삭제
     */
    public function deleteTemplate(int $templateId): void
    {
        ApiTemplate::where('id', $templateId)->delete();
    }

    /*
    |--------------------------------------------------------------------------
    | History Operations
    |--------------------------------------------------------------------------
    */

    /**
     * 요청 기록 저장
     */
    public function logRequest(int $userId, array $data): ApiHistory
    {
        // 최대 개수 초과 시 오래된 것 삭제
        $maxEntries = config('api-explorer.history.max_entries', 100);
        $count = ApiHistory::where('user_id', $userId)->count();

        if ($count >= $maxEntries) {
            $deleteCount = $count - $maxEntries + 1;
            ApiHistory::where('user_id', $userId)
                ->oldest('created_at')
                ->limit($deleteCount)
                ->delete();
        }

        return ApiHistory::create([
            'user_id' => $userId,
            'endpoint' => $data['endpoint'],
            'method' => strtoupper($data['method']),
            'request_headers' => $data['request_headers'] ?? null,
            'request_body' => $data['request_body'] ?? null,
            'response_status' => $data['response_status'],
            'response_headers' => $data['response_headers'] ?? null,
            'response_body' => $data['response_body'] ?? null,
            'duration_ms' => $data['duration_ms'],
            'environment' => $data['environment'],
        ]);
    }

    /**
     * 히스토리 조회
     */
    public function getHistory(int $userId, int $limit = 50): Collection
    {
        return ApiHistory::where('user_id', $userId)
            ->latest('created_at')
            ->limit($limit)
            ->get();
    }

    /**
     * 히스토리 삭제
     */
    public function clearHistory(int $userId): int
    {
        return ApiHistory::where('user_id', $userId)->delete();
    }

    /**
     * 단일 히스토리 조회
     */
    public function getHistoryItem(int $historyId): ?ApiHistory
    {
        return ApiHistory::find($historyId);
    }

    /*
    |--------------------------------------------------------------------------
    | Environment Operations
    |--------------------------------------------------------------------------
    */

    /**
     * 환경 목록 조회
     */
    public function getEnvironments(int $userId): Collection
    {
        return ApiEnvironment::where('user_id', $userId)
            ->orderBy('is_default', 'desc')
            ->orderBy('name')
            ->get();
    }

    /**
     * 환경 저장
     */
    public function saveEnvironment(int $userId, array $data): ApiEnvironment
    {
        // 기본 환경으로 설정 시 기존 기본 해제
        if ($data['is_default'] ?? false) {
            ApiEnvironment::where('user_id', $userId)
                ->update(['is_default' => false]);
        }

        return ApiEnvironment::create([
            'user_id' => $userId,
            'name' => $data['name'],
            'base_url' => $data['base_url'],
            'api_key' => $data['api_key'] ?? null,
            'auth_token' => $data['auth_token'] ?? null,
            'variables' => $data['variables'] ?? null,
            'is_default' => $data['is_default'] ?? false,
        ]);
    }

    /**
     * 환경 수정
     */
    public function updateEnvironment(int $environmentId, array $data): ApiEnvironment
    {
        $environment = ApiEnvironment::findOrFail($environmentId);

        // 기본 환경으로 설정 시 기존 기본 해제
        if ($data['is_default'] ?? false) {
            ApiEnvironment::where('user_id', $environment->user_id)
                ->where('id', '!=', $environmentId)
                ->update(['is_default' => false]);
        }

        $environment->update($data);

        return $environment->fresh();
    }

    /**
     * 환경 삭제
     */
    public function deleteEnvironment(int $environmentId): void
    {
        ApiEnvironment::where('id', $environmentId)->delete();
    }

    /**
     * 기본 환경 설정
     */
    public function setDefaultEnvironment(int $userId, int $environmentId): void
    {
        // 기존 기본 해제
        ApiEnvironment::where('user_id', $userId)
            ->update(['is_default' => false]);

        // 새 기본 설정
        ApiEnvironment::where('id', $environmentId)
            ->where('user_id', $userId)
            ->update(['is_default' => true]);
    }

    /**
     * 기본 환경 조회
     */
    public function getDefaultEnvironment(int $userId): ?ApiEnvironment
    {
        return ApiEnvironment::where('user_id', $userId)
            ->where('is_default', true)
            ->first();
    }

    /**
     * 기본 환경 초기화 (설정된 환경이 없는 경우)
     */
    public function initializeDefaultEnvironments(int $userId): void
    {
        $count = ApiEnvironment::where('user_id', $userId)->count();

        if ($count > 0) {
            return;
        }

        $defaults = config('api-explorer.default_environments', []);

        foreach ($defaults as $index => $env) {
            $this->saveEnvironment($userId, [
                'name' => $env['name'],
                'base_url' => $env['base_url'],
                'api_key' => $env['api_key'] ?? null,
                'is_default' => $index === 0,
            ]);
        }
    }
}
