<?php

namespace App\Http\Controllers\Web\Bo;

use App\Http\Controllers\Controller;
use App\Models\User;
use App\Services\AdminAuditLogger;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Illuminate\View\View;

class UserController extends Controller
{
    public function index(Request $request): View
    {
        $search = trim((string) $request->string('q'));
        $role = trim((string) $request->string('role'));
        $kyc = trim((string) $request->string('kyc'));
        $activity = trim((string) $request->string('activity'));
        $hasPaymentMethodsTable = Schema::hasTable('user_payment_methods');

        $usersQuery = User::query()
            ->withCount(['clientMissions', 'linerMissions', 'kycDocuments'])
            ->when($search !== '', function ($query) use ($search): void {
                $query->where(function ($subQuery) use ($search): void {
                    $subQuery
                        ->where('name', 'like', '%' . $search . '%')
                        ->orWhere('email', 'like', '%' . $search . '%')
                        ->orWhere('phone', 'like', '%' . $search . '%');
                });
            })
            ->when($role !== '', fn ($query) => $query->where('role', $role))
            ->when(
                $kyc === 'verified',
                fn ($query) => $query->where('role', '!=', 'admin')->where('is_kyc_verified', true),
                fn ($query) => $kyc === 'pending'
                    ? $query->where('role', '!=', 'admin')->where('is_kyc_verified', false)
                    : null,
            )
            ->when($activity === 'online', fn ($query) => $query->where('last_seen_at', '>=', now()->subDay()))
            ->when($activity === 'inactive', fn ($query) => $query->where(function ($subQuery): void {
                $subQuery->whereNull('last_seen_at')->orWhere('last_seen_at', '<', now()->subDays(30));
            }));

        if ($hasPaymentMethodsTable) {
            $usersQuery->withCount('paymentMethods');
        } else {
            $usersQuery->addSelect(DB::raw('0 as payment_methods_count'));
        }

        $users = $usersQuery
            ->latest()
            ->paginate(20)
            ->withQueryString();

        return view('bo.users.index', [
            'users' => $users,
            'search' => $search,
            'role' => $role,
            'kyc' => $kyc,
            'activity' => $activity,
            'hasPaymentMethodsTable' => $hasPaymentMethodsTable,
        ]);
    }

    public function create(): View
    {
        return view('bo.users.create');
    }

    public function store(Request $request, AdminAuditLogger $auditLogger): RedirectResponse
    {
        $data = $request->validate([
            'name' => ['required', 'string', 'max:120'],
            'email' => ['required', 'email', 'max:180', 'unique:users,email'],
            'role' => ['required', Rule::in(['admin', 'client', 'liner'])],
            'phone' => ['nullable', 'string', 'max:30'],
            'bio' => ['nullable', 'string', 'max:500'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
            'is_kyc_verified' => ['nullable', 'boolean'],
            'language' => ['nullable', 'string', 'min:2', 'max:10'],
            'region' => ['nullable', 'string', 'min:2', 'max:10'],
            'push_notifications_enabled' => ['nullable', 'boolean'],
            'sms_notifications_enabled' => ['nullable', 'boolean'],
            'email_notifications_enabled' => ['nullable', 'boolean'],
            'email_marketing_enabled' => ['nullable', 'boolean'],
        ]);

        $user = User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'role' => $data['role'],
            'phone' => $data['phone'] ?? null,
            'bio' => $data['bio'] ?? null,
            'is_kyc_verified' => $this->resolveKycFlag($data),
            'language' => strtolower((string) ($data['language'] ?? 'fr')),
            'region' => strtoupper((string) ($data['region'] ?? 'FR')),
            'push_notifications_enabled' => (bool) ($data['push_notifications_enabled'] ?? true),
            'sms_notifications_enabled' => (bool) ($data['sms_notifications_enabled'] ?? false),
            'email_notifications_enabled' => (bool) ($data['email_notifications_enabled'] ?? true),
            'email_marketing_enabled' => (bool) ($data['email_marketing_enabled'] ?? true),
            'password' => $data['password'],
        ]);

        $auditLogger->log(
            admin: $request->user(),
            action: 'bo.users.create',
            auditable: $user,
            metadata: [
                'role' => $user->role,
            ],
        );

        return redirect()
            ->route('bo.users.index')
            ->with('status', sprintf('Utilisateur #%d cree.', $user->id));
    }

    public function edit(User $user): View
    {
        return view('bo.users.edit', [
            'targetUser' => $user,
        ]);
    }

    public function update(Request $request, User $user, AdminAuditLogger $auditLogger): RedirectResponse
    {
        $data = $request->validate([
            'name' => ['required', 'string', 'max:120'],
            'email' => ['required', 'email', 'max:180', Rule::unique('users', 'email')->ignore($user->id)],
            'role' => ['required', Rule::in(['admin', 'client', 'liner'])],
            'phone' => ['nullable', 'string', 'max:30'],
            'bio' => ['nullable', 'string', 'max:500'],
            'password' => ['nullable', 'string', 'min:8', 'confirmed'],
            'is_kyc_verified' => ['nullable', 'boolean'],
            'language' => ['nullable', 'string', 'min:2', 'max:10'],
            'region' => ['nullable', 'string', 'min:2', 'max:10'],
            'push_notifications_enabled' => ['nullable', 'boolean'],
            'sms_notifications_enabled' => ['nullable', 'boolean'],
            'email_notifications_enabled' => ['nullable', 'boolean'],
            'email_marketing_enabled' => ['nullable', 'boolean'],
        ]);

        $updatePayload = [
            'name' => $data['name'],
            'email' => $data['email'],
            'role' => $data['role'],
            'phone' => $data['phone'] ?? null,
            'bio' => $data['bio'] ?? null,
            'is_kyc_verified' => $this->resolveKycFlag($data),
            'language' => strtolower((string) ($data['language'] ?? 'fr')),
            'region' => strtoupper((string) ($data['region'] ?? 'FR')),
            'push_notifications_enabled' => (bool) ($data['push_notifications_enabled'] ?? true),
            'sms_notifications_enabled' => (bool) ($data['sms_notifications_enabled'] ?? false),
            'email_notifications_enabled' => (bool) ($data['email_notifications_enabled'] ?? true),
            'email_marketing_enabled' => (bool) ($data['email_marketing_enabled'] ?? true),
        ];

        if (!empty($data['password'])) {
            $updatePayload['password'] = $data['password'];
        }

        $user->update($updatePayload);

        $auditLogger->log(
            admin: $request->user(),
            action: 'bo.users.update',
            auditable: $user,
            metadata: [
                'role' => $user->role,
            ],
        );

        return redirect()
            ->route('bo.users.index')
            ->with('status', sprintf('Utilisateur #%d mis a jour.', $user->id));
    }

    public function destroy(Request $request, User $user, AdminAuditLogger $auditLogger): RedirectResponse
    {
        $currentAdmin = $request->user();

        if ($currentAdmin && $currentAdmin->id === $user->id) {
            return back()->withErrors(['status' => 'Impossible de supprimer le compte admin connecte.']);
        }

        if (strtolower((string) $user->role) === 'admin' && User::where('role', 'admin')->count() <= 1) {
            return back()->withErrors(['status' => 'Impossible de supprimer le dernier admin.']);
        }

        $auditLogger->log(
            admin: $request->user(),
            action: 'bo.users.delete',
            auditable: $user,
            metadata: [
                'email' => $user->email,
            ],
        );

        $user->delete();

        return redirect()
            ->route('bo.users.index')
            ->with('status', 'Utilisateur supprime.');
    }

    private function resolveKycFlag(array $data): bool
    {
        if (($data['role'] ?? null) === 'admin') {
            // KYC is not required for BO admins.
            return true;
        }

        return (bool) ($data['is_kyc_verified'] ?? false);
    }
}
