<?php

namespace App\Http\Controllers;

use App\Models\Round;
use App\Services\CityPayoutService;
use App\Services\PlatformMetricsService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

class AdminAuthController extends Controller
{
    public function showLogin(Request $request)
    {
        if ($request->session()->get('admin.authenticated') === true) {
            return redirect()->route('admin.dashboard');
        }

        return view('admin.login');
    }

    public function login(Request $request)
    {
        $credentials = $request->validate([
            'email' => ['required', 'email'],
            'password' => ['required', 'string'],
        ]);

        $adminEmail = (string) env('ADMIN_EMAIL', 'admin@survive.local');
        $adminPassword = (string) env('ADMIN_PASSWORD', 'admin123456');

        $emailMatches = hash_equals(strtolower($adminEmail), strtolower($credentials['email']));
        $passwordMatches = hash_equals($adminPassword, $credentials['password']);

        if (! $emailMatches || ! $passwordMatches) {
            return back()
                ->withErrors(['login' => 'Credenciais inválidas.'])
                ->onlyInput('email');
        }

        $request->session()->regenerate();
        $request->session()->put('admin.authenticated', true);
        $request->session()->put('admin.email', $adminEmail);

        return redirect()->route('admin.dashboard');
    }

    public function dashboard(
        Request $request,
        PlatformMetricsService $metricsService,
        CityPayoutService $cityPayoutService
    )
    {
        if ($request->session()->get('admin.authenticated') !== true) {
            return redirect()->route('admin.login');
        }

        $snapshot = $metricsService->snapshot();

        return view('admin.dashboard', [
            'adminEmail' => (string) $request->session()->get('admin.email'),
            'stats' => $snapshot['adminStats'],
            'statesCities' => config('br_states_cities', []),
            'cityPayoutSettings' => $cityPayoutService->listSettings(),
            'defaultPrizePercentage' => CityPayoutService::DEFAULT_PRIZE_PERCENTAGE,
        ]);
    }

    public function cityPayout(Request $request, CityPayoutService $cityPayoutService)
    {
        if ($request->session()->get('admin.authenticated') !== true) {
            return redirect()->route('admin.login');
        }

        return view('admin.city-payout', [
            'adminEmail' => (string) $request->session()->get('admin.email'),
            'statesCities' => config('br_states_cities', []),
            'cityPayoutSettings' => $cityPayoutService->listSettings(),
            'defaultPrizePercentage' => CityPayoutService::DEFAULT_PRIZE_PERCENTAGE,
        ]);
    }

    public function saveCityPayout(Request $request, CityPayoutService $cityPayoutService): RedirectResponse
    {
        if ($request->session()->get('admin.authenticated') !== true) {
            return redirect()->route('admin.login');
        }

        $data = $request->validate([
            'state' => ['required', 'string', 'size:2'],
            'city' => ['required', 'string', 'max:120'],
            'prize_percentage' => ['required', 'numeric', 'min:0', 'max:100'],
            'apply_to_open_rounds' => ['nullable', 'boolean'],
        ]);

        $state = strtoupper(trim($data['state']));
        $city = $this->normalizeCity($data['city']);
        $statesCities = config('br_states_cities', []);

        if (! array_key_exists($state, $statesCities)) {
            return back()
                ->withErrors(['state' => 'Estado inválido.'])
                ->withInput();
        }

        if (! $this->cityExistsInState($city, $statesCities[$state])) {
            return back()
                ->withErrors(['city' => 'Cidade inválida para o estado selecionado.'])
                ->withInput();
        }

        $prizePercentage = round((float) $data['prize_percentage'], 2);
        $saved = $cityPayoutService->upsertSetting($state, $city, $prizePercentage);

        if (! $saved) {
            return back()
                ->withErrors(['state' => 'Tabela de configuração não encontrada. Rode as migrações e tente novamente.'])
                ->withInput();
        }

        $openRoundsUpdated = 0;
        $shouldApply = (bool) ($data['apply_to_open_rounds'] ?? false);

        if ($shouldApply) {
            $query = Round::query()
                ->where('status', 'open')
                ->where('state', $state)
                ->where('city', $city);

            $openRoundsUpdated = (int) $query->count();

            $query->chunkById(200, function ($rounds) use ($cityPayoutService) {
                foreach ($rounds as $round) {
                    $grossAmount = ((float) $round->entry_price) * ((int) $round->total_entries);
                    $round->update([
                        'prize_total' => $cityPayoutService->calculatePrizeAmount($grossAmount, $round->state, $round->city),
                    ]);
                }
            });
        }

        $housePercentage = $cityPayoutService->getHousePercentage($prizePercentage);

        return redirect()
            ->route('admin.city-payout.index')
            ->with('status', 'Configuração salva para ' . $city . '/' . $state
                . ': prêmio ' . number_format($prizePercentage, 2, ',', '.') . '% e casa '
                . number_format($housePercentage, 2, ',', '.') . '%.'
                . ($shouldApply ? ' Rodadas abertas atualizadas: ' . $openRoundsUpdated . '.' : ''));
    }

    public function mercadoPago(Request $request)
    {
        if ($request->session()->get('admin.authenticated') !== true) {
            return redirect()->route('admin.login');
        }

        $settings = [
            'pix_enabled' => false,
            'sandbox_enabled' => true,
            'mercado_pago_public_key' => '',
            'mercado_pago_access_token' => '',
            'pix_key' => '',
            'pix_key_holder' => '',
            'notification_email' => '',
            'webhook_url' => '',
        ];

        if (Schema::hasTable('payment_pix_settings')) {
            $row = DB::table('payment_pix_settings')->orderBy('id')->first();

            if ($row !== null) {
                $settings = [
                    'pix_enabled' => (bool) $row->pix_enabled,
                    'sandbox_enabled' => (bool) $row->sandbox_enabled,
                    'mercado_pago_public_key' => (string) ($row->mercado_pago_public_key ?? ''),
                    'mercado_pago_access_token' => (string) ($row->mercado_pago_access_token ?? ''),
                    'pix_key' => (string) ($row->pix_key ?? ''),
                    'pix_key_holder' => (string) ($row->pix_key_holder ?? ''),
                    'notification_email' => (string) ($row->notification_email ?? ''),
                    'webhook_url' => (string) ($row->webhook_url ?? ''),
                ];
            }
        }

        return view('admin.mercado-pago', [
            'adminEmail' => (string) $request->session()->get('admin.email'),
            'settings' => $settings,
        ]);
    }

    public function saveMercadoPago(Request $request): RedirectResponse
    {
        if ($request->session()->get('admin.authenticated') !== true) {
            return redirect()->route('admin.login');
        }

        if (! Schema::hasTable('payment_pix_settings')) {
            return back()
                ->withErrors(['mercado_pago_public_key' => 'Tabela de configuração PIX não encontrada. Rode as migrações e tente novamente.'])
                ->withInput();
        }

        $data = $request->validate([
            'mercado_pago_public_key' => ['nullable', 'string', 'max:255'],
            'mercado_pago_access_token' => ['nullable', 'string', 'max:2000'],
            'pix_key' => ['nullable', 'string', 'max:255'],
            'pix_key_holder' => ['nullable', 'string', 'max:120'],
            'notification_email' => ['nullable', 'email', 'max:190'],
            'webhook_url' => ['nullable', 'url', 'max:255'],
            'pix_enabled' => ['nullable', 'boolean'],
            'sandbox_enabled' => ['nullable', 'boolean'],
        ]);

        $payload = [
            'pix_enabled' => (bool) ($data['pix_enabled'] ?? false),
            'sandbox_enabled' => (bool) ($data['sandbox_enabled'] ?? false),
            'mercado_pago_public_key' => $data['mercado_pago_public_key'] ?? null,
            'mercado_pago_access_token' => $data['mercado_pago_access_token'] ?? null,
            'pix_key' => $data['pix_key'] ?? null,
            'pix_key_holder' => $data['pix_key_holder'] ?? null,
            'notification_email' => $data['notification_email'] ?? null,
            'webhook_url' => $data['webhook_url'] ?? null,
            'updated_at' => now(),
        ];

        if (! DB::table('payment_pix_settings')->where('id', 1)->exists()) {
            $payload['created_at'] = now();
        }

        DB::table('payment_pix_settings')->updateOrInsert(['id' => 1], $payload);

        return redirect()
            ->route('admin.mercadopago.index')
            ->with('status', 'Configurações do Mercado Pago PIX salvas com sucesso.');
    }

    public function logout(Request $request)
    {
        $request->session()->forget('admin.authenticated');
        $request->session()->forget('admin.email');
        $request->session()->regenerateToken();

        return redirect()->route('admin.login');
    }

    private function normalizeCity(string $city): string
    {
        $clean = preg_replace('/\s+/', ' ', trim($city)) ?? trim($city);

        return mb_convert_case($clean, MB_CASE_TITLE, 'UTF-8');
    }

    private function cityExistsInState(string $city, array $cities): bool
    {
        foreach ($cities as $candidate) {
            if ($this->normalizeCity($candidate) === $city) {
                return true;
            }
        }

        return false;
    }
}
