<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\ApiSetting;
use App\Services\FmpEconomicCalendarService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\View\View;

class ApiSettingController extends Controller
{
    public function index(): View
    {
        return view('admin.api-settings.index', [
            'settings' => ApiSetting::latest()->paginate(10),
        ]);
    }

    public function create(): View
    {
        return view('admin.api-settings.create', [
            'setting' => new ApiSetting(['status' => 'active']),
            'providers' => ApiSetting::providers(),
            'keyNames' => ApiSetting::keyNames(),
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        $data = $this->validatedData($request);
        $data['key_name'] = ApiSetting::keyNames()[$data['provider_name']];

        if ($data['status'] === 'active') {
            $this->deactivateProvider($data['provider_name']);
        }

        $setting = ApiSetting::create($data);

        return redirect()
            ->route('admin.api-settings.show', $setting)
            ->with('success', 'API setting saved successfully.');
    }

    public function show(ApiSetting $apiSetting): View
    {
        return view('admin.api-settings.show', [
            'setting' => $apiSetting,
        ]);
    }

    public function edit(ApiSetting $apiSetting): View
    {
        return view('admin.api-settings.edit', [
            'setting' => $apiSetting,
            'providers' => ApiSetting::providers(),
            'keyNames' => ApiSetting::keyNames(),
        ]);
    }

    public function update(Request $request, ApiSetting $apiSetting): RedirectResponse
    {
        $data = $this->validatedData($request, updating: true);
        $data['key_name'] = ApiSetting::keyNames()[$data['provider_name']];

        if (! filled($data['api_key'] ?? null)) {
            unset($data['api_key']);
        }

        if ($data['status'] === 'active') {
            $this->deactivateProvider($data['provider_name'], $apiSetting->id);
        }

        $apiSetting->update($data);

        return redirect()
            ->route('admin.api-settings.show', $apiSetting)
            ->with('success', 'API setting updated successfully.');
    }

    public function destroy(ApiSetting $apiSetting): RedirectResponse
    {
        $apiSetting->delete();

        return redirect()
            ->route('admin.api-settings.index')
            ->with('success', 'API setting deleted successfully.');
    }

    public function toggleStatus(ApiSetting $apiSetting): RedirectResponse
    {
        $newStatus = $apiSetting->isActive() ? 'inactive' : 'active';

        if ($newStatus === 'active') {
            $this->deactivateProvider($apiSetting->provider_name, $apiSetting->id);
        }

        $apiSetting->update(['status' => $newStatus]);

        return back()->with('success', 'API setting status updated successfully.');
    }

    public function test(ApiSetting $apiSetting, FmpEconomicCalendarService $fmpService): RedirectResponse
    {
        if ($apiSetting->provider_name === ApiSetting::PROVIDER_METAAPI) {
            return back()->with('error', 'MetaApi testing is prepared for future integration.');
        }

        $result = $fmpService->testKey((string) $apiSetting->decryptedApiKey());

        return back()->with($result['status'] === 'success' ? 'success' : 'error', $result['message']);
    }

    private function validatedData(Request $request, bool $updating = false): array
    {
        return Validator::make($request->all(), [
            'provider_name' => ['required', Rule::in(array_keys(ApiSetting::providers()))],
            'api_key' => [$updating ? 'nullable' : 'required', 'string', 'max:2000'],
            'status' => ['required', Rule::in(['active', 'inactive'])],
        ])->validate();
    }

    private function deactivateProvider(string $provider, ?int $exceptId = null): void
    {
        ApiSetting::query()
            ->where('provider_name', $provider)
            ->when($exceptId, fn ($query) => $query->whereKeyNot($exceptId))
            ->update(['status' => 'inactive']);
    }
}
