<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

class WebAdminController extends Controller
{
    public function login()
    {
        if (Auth::check() && Auth::user()->isAdmin()) {
            return redirect()->route('admin.dashboard');
        }

        return view('admin.login');
    }

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

        $field = filter_var($credentials['email'], FILTER_VALIDATE_EMAIL) ? 'email' : 'phone';

        if (! Auth::attempt([$field => $credentials['email'], 'password' => $credentials['password'], 'status' => 'active'], true)) {
            return back()->withErrors(['email' => 'Invalid admin login.'])->onlyInput('email');
        }

        if (! Auth::user()->isAdmin()) {
            Auth::logout();
            return back()->withErrors(['email' => 'This account is not admin.'])->onlyInput('email');
        }

        $request->session()->regenerate();

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

    public function logout(Request $request)
    {
        Auth::logout();
        $request->session()->invalidate();
        $request->session()->regenerateToken();

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

    public function dashboard()
    {
        $this->guard();

        $today = now()->toDateString();
        $stats = [
            ['label' => 'Today Bookings', 'value' => DB::table('bookings')->whereDate('created_at', $today)->count(), 'tone' => 'blue'],
            ['label' => 'Today Income', 'value' => 'Rs ' . number_format((float) DB::table('payments')->where('status', 'captured')->whereDate('created_at', $today)->sum('amount'), 2), 'tone' => 'green'],
            ['label' => 'Customers', 'value' => DB::table('users')->where('role', 'customer')->count(), 'tone' => 'orange'],
            ['label' => 'Experts', 'value' => DB::table('professionals')->count(), 'tone' => 'purple'],
            ['label' => 'Online Experts', 'value' => DB::table('professionals')->where('online_status', 'online')->count(), 'tone' => 'green'],
            ['label' => 'Open SOS', 'value' => DB::table('sos_alerts')->where('status', 'open')->count(), 'tone' => 'red'],
        ];

        $graph = [
            'Bookings' => max(1, DB::table('bookings')->count()),
            'Customers' => max(1, DB::table('users')->where('role', 'customer')->count()),
            'Experts' => max(1, DB::table('professionals')->count()),
            'Tickets' => max(1, DB::table('support_tickets')->count()),
            'Complaints' => max(1, DB::table('complaints')->count()),
        ];

        return view('admin.dashboard', [
            'stats' => $stats,
            'graph' => $graph,
            'income' => [
                'paid' => DB::table('payments')->where('status', 'captured')->sum('amount'),
                'refunds' => DB::table('refunds')->sum('amount'),
                'vendor_wallet' => DB::table('professionals')->sum('wallet_balance'),
            ],
            'latestBookings' => DB::table('bookings')->latest('id')->limit(10)->get(),
            'latestVendors' => DB::table('professionals')->latest('id')->limit(10)->get(),
        ]);
    }

    public function moduleIndex(string $module)
    {
        $this->guard();
        $config = $this->module($module);
        $rows = DB::table($config['table'])->latest('id')->paginate(30);

        return view('admin.modules.index', compact('module', 'config', 'rows'));
    }

    public function moduleCreate(string $module)
    {
        $this->guard();
        $config = $this->module($module);
        $row = null;

        return view('admin.modules.form', compact('module', 'config', 'row'));
    }

    public function moduleStore(Request $request, string $module)
    {
        $this->guard();
        $config = $this->module($module);
        $data = $this->cleanPayload($request, $config);
        $data['created_at'] = now();
        $data['updated_at'] = now();

        if ($module === 'staff') {
            $userId = DB::table('users')->insertGetId([
                'uuid' => (string) Str::uuid(),
                'name' => $data['name'] ?? 'Staff',
                'email' => $data['email'] ?? null,
                'phone' => $data['phone'] ?? ('9' . random_int(100000000, 999999999)),
                'phone_country_code' => '+91',
                'role' => $data['role'] ?? 'support_agent',
                'status' => $data['status'] ?? 'active',
                'password' => Hash::make($request->input('password', 'staff12345')),
                'created_at' => now(),
                'updated_at' => now(),
            ]);
            DB::table('staff_profiles')->insert([
                'user_id' => $userId,
                'admin_role_id' => $request->input('admin_role_id'),
                'employee_code' => $request->input('employee_code', 'RS-STF-' . strtoupper(Str::random(5))),
                'department' => $request->input('department'),
                'designation' => $request->input('designation'),
                'status' => $data['status'] ?? 'active',
                'created_at' => now(),
                'updated_at' => now(),
            ]);

            return redirect()->route('admin.module.index', $module)->with('status', 'Staff created.');
        }

        if ($module === 'customers') {
            $data['uuid'] = (string) Str::uuid();
            $data['phone_country_code'] = '+91';
            $data['role'] = 'customer';
            $data['password'] = Hash::make($request->input('password', 'customer123'));
        }

        if ($module === 'vendors') {
            $userId = DB::table('users')->insertGetId([
                'uuid' => (string) Str::uuid(),
                'name' => $request->input('name', 'Expert'),
                'email' => $request->input('email'),
                'phone' => $request->input('phone', '7' . random_int(100000000, 999999999)),
                'phone_country_code' => '+91',
                'role' => 'professional',
                'status' => 'active',
                'password' => Hash::make($request->input('password', 'expert123')),
                'created_at' => now(),
                'updated_at' => now(),
            ]);
            unset($data['name'], $data['email'], $data['phone'], $data['password']);
            $data['user_id'] = $userId;
            $data['pro_code'] = $request->input('pro_code', 'RS-PRO-' . strtoupper(Str::random(5)));
        }

        if ($module === 'services') {
            $data['slug'] = $data['slug'] ?? Str::slug($data['name']) . '-' . strtolower(Str::random(4));
            $data['image_slider_json'] = $this->jsonFromLines($request->input('image_slider_json'));
        }

        $data = $this->applyModuleDefaults($module, $data);

        if (in_array($module, ['packages'], true)) {
            $data['service_ids_json'] = $this->jsonFromLines($request->input('service_ids_json'));
        }

        $id = DB::table($config['table'])->insertGetId($data);

        return redirect()->route('admin.module.index', $module)->with('status', $config['title'] . ' created.');
    }

    public function moduleEdit(string $module, int $id)
    {
        $this->guard();
        $config = $this->module($module);
        $row = DB::table($config['table'])->where('id', $id)->first();

        abort_if(! $row, 404);

        return view('admin.modules.form', compact('module', 'config', 'row'));
    }

    public function moduleUpdate(Request $request, string $module, int $id)
    {
        $this->guard();
        $config = $this->module($module);
        $data = $this->cleanPayload($request, $config);
        $data['updated_at'] = now();

        if ($module === 'staff') {
            $userData = collect($data)->only(['name', 'email', 'phone', 'role', 'status'])->toArray();
            if ($request->filled('password')) {
                $userData['password'] = Hash::make($request->input('password'));
            }
            $userData['updated_at'] = now();
            DB::table('users')->where('id', $id)->update($userData);

            DB::table('staff_profiles')->where('user_id', $id)->update([
                'admin_role_id' => $request->input('admin_role_id'),
                'employee_code' => $request->input('employee_code'),
                'department' => $request->input('department'),
                'designation' => $request->input('designation'),
                'status' => $request->input('status', 'active'),
                'updated_at' => now(),
            ]);

            return redirect()->route('admin.module.index', $module)->with('status', 'Staff updated.');
        }

        if ($module === 'customers') {
            if ($request->filled('password')) {
                $data['password'] = Hash::make($request->input('password'));
            } else {
                unset($data['password']);
            }
        }

        if ($module === 'vendors') {
            $vendor = DB::table($config['table'])->where('id', $id)->first();
            if ($vendor && $vendor->user_id) {
                $userData = [];
                foreach (['name', 'email', 'phone'] as $field) {
                    if ($request->filled($field)) {
                        $userData[$field] = $request->input($field);
                    }
                }
                if ($request->filled('password')) {
                    $userData['password'] = Hash::make($request->input('password'));
                }
                if ($userData) {
                    $userData['updated_at'] = now();
                    DB::table('users')->where('id', $vendor->user_id)->update($userData);
                }
            }
            unset($data['name'], $data['email'], $data['phone'], $data['password']);
        }

        if ($module === 'services' && isset($data['image_slider_json'])) {
            $data['image_slider_json'] = $this->jsonFromLines($request->input('image_slider_json'));
        }
        if ($module === 'packages' && isset($data['service_ids_json'])) {
            $data['service_ids_json'] = $this->jsonFromLines($request->input('service_ids_json'));
        }

        DB::table($config['table'])->where('id', $id)->update($data);

        return redirect()->route('admin.module.index', $module)->with('status', $config['title'] . ' updated.');
    }

    public function moduleDestroy(string $module, int $id)
    {
        $this->guard();
        $config = $this->module($module);
        DB::table($config['table'])->where('id', $id)->delete();

        return redirect()->route('admin.module.index', $module)->with('status', $config['title'] . ' deleted.');
    }

    public function liveTracking()
    {
        $this->guard();

        return view('admin.tracking', [
            'experts' => DB::table('professionals')
                ->leftJoin('users', 'users.id', '=', 'professionals.user_id')
                ->leftJoin('professional_locations', 'professional_locations.professional_id', '=', 'professionals.id')
                ->select('professionals.*', 'users.name', 'users.phone', 'professional_locations.lat', 'professional_locations.lng', 'professional_locations.captured_at')
                ->latest('professional_locations.captured_at')
                ->limit(100)
                ->get(),
            'mapKey' => DB::table('map_settings')->where('provider', 'google')->value('api_key'),
        ]);
    }

    public function reports()
    {
        $this->guard();

        return view('admin.reports', [
            'cards' => [
                'Total Income' => DB::table('payments')->where('status', 'captured')->sum('amount'),
                'Refunds' => DB::table('refunds')->sum('amount'),
                'Vendor Wallet' => DB::table('professionals')->sum('wallet_balance'),
                'Rapid Coins' => DB::table('rapid_coin_transactions')->sum('coins'),
                'Bookings' => DB::table('bookings')->count(),
                'Complaints' => DB::table('complaints')->count(),
            ],
            'bookings' => DB::table('bookings')->latest('id')->limit(30)->get(),
        ]);
    }

    private function module(string $module): array
    {
        $modules = $this->modules();
        abort_if(! isset($modules[$module]), 404);

        return $modules[$module];
    }

    private function modules(): array
    {
        return config('rapidsewa_admin.modules');
    }

    private function cleanPayload(Request $request, array $config): array
    {
        $data = [];
        foreach ($config['fields'] as $field => $meta) {
            if (! $request->has($field)) {
                continue;
            }
            $value = $request->input($field);
            if (($meta['type'] ?? 'text') === 'checkbox') {
                $value = $request->boolean($field);
            }
            if (($meta['type'] ?? 'text') === 'number' && $value !== null && $value !== '') {
                $value = is_numeric($value) ? $value : 0;
            }
            $data[$field] = $value === '' ? null : $value;
        }

        return $data;
    }

    private function applyModuleDefaults(string $module, array $data): array
    {
        $defaults = [
            'bookings' => ['booking_number' => 'BK-' . now()->format('Ymd') . '-' . strtoupper(Str::random(6))],
            'hourly-bookings' => ['booking_number' => 'HB-' . now()->format('Ymd') . '-' . strtoupper(Str::random(6)), 'booking_type' => 'hourly'],
            'support-tickets' => ['ticket_number' => 'TK-' . now()->format('Ymd') . '-' . strtoupper(Str::random(6))],
            'complaints' => ['complaint_number' => 'CMP-' . now()->format('Ymd') . '-' . strtoupper(Str::random(6))],
            'sos' => ['sos_number' => 'SOS-' . now()->format('Ymd') . '-' . strtoupper(Str::random(6))],
            'cities' => ['slug' => isset($data['name']) ? Str::slug($data['name']) : strtolower(Str::random(6))],
            'localities' => ['slug' => isset($data['name']) ? Str::slug($data['name']) : strtolower(Str::random(6))],
            'service-categories' => ['slug' => isset($data['name']) ? Str::slug($data['name']) : strtolower(Str::random(6))],
            'roles' => ['slug' => isset($data['name']) ? Str::slug($data['name']) : strtolower(Str::random(6))],
            'payment-gateways' => ['slug' => isset($data['name']) ? Str::slug($data['name']) : strtolower(Str::random(6))],
        ];

        foreach (($defaults[$module] ?? []) as $field => $value) {
            if (! isset($data[$field]) || $data[$field] === null || $data[$field] === '') {
                $data[$field] = $value;
            }
        }

        return $data;
    }

    private function jsonFromLines(?string $value): ?string
    {
        if (! $value) {
            return null;
        }

        $decoded = json_decode($value, true);
        if (json_last_error() === JSON_ERROR_NONE) {
            return json_encode($decoded);
        }

        return json_encode(array_values(array_filter(array_map('trim', preg_split('/\r\n|\r|\n/', $value)))));
    }

    private function guard(): void
    {
        if (! Auth::check() || ! Auth::user()->isAdmin()) {
            abort(403, 'Admin login required.');
        }
    }
}
