<?php

namespace App\Http\Controllers;

use App\Models\Customer;
use App\Models\LoanProduct;
use App\Models\SavingsAccount;
use App\Models\SavingsProduct;
use App\Models\Tenant;
use App\Models\User;
use App\Services\ActivityLogger;
use App\Services\BranchService;
use App\Services\KycVerificationService;
use App\Services\NumberGenerator;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\View\View;

class PublicTenantController extends Controller
{
    public function show(Tenant $tenant): View
    {
        abort_unless($tenant->status === 'active', 404);
        SavingsProduct::createDefaultsForTenant($tenant);

        return view('public.tenant-show', [
            'tenant' => $tenant,
            'products' => LoanProduct::withoutGlobalScopes()
                ->where('tenant_id', $tenant->id)
                ->where('is_active', true)
                ->where('show_on_public_website', true)
                ->orderBy('name')
                ->get(),
            'savingsProducts' => SavingsProduct::withoutGlobalScopes()
                ->where('tenant_id', $tenant->id)
                ->where('is_active', true)
                ->where('show_on_public_website', true)
                ->orderBy('name')
                ->get(),
            'stats' => [
                'customers' => Customer::withoutGlobalScopes()->where('tenant_id', $tenant->id)->count(),
                'savings' => SavingsAccount::withoutGlobalScopes()->where('tenant_id', $tenant->id)->sum('balance'),
            ],
        ]);
    }

    public function register(Tenant $tenant): View
    {
        abort_unless($tenant->status === 'active', 404);

        return view('public.tenant-register', compact('tenant'));
    }

    public function storeRegistration(Request $request, Tenant $tenant, KycVerificationService $kyc, BranchService $branches): RedirectResponse
    {
        abort_unless($tenant->status === 'active', 404);
        SavingsProduct::createDefaultsForTenant($tenant);

        $validated = $request->validate([
            'first_name' => ['required', 'string', 'max:100'],
            'middle_name' => ['nullable', 'string', 'max:100'],
            'last_name' => ['required', 'string', 'max:100'],
            'email' => ['required', 'email', 'max:255', 'unique:users,email'],
            'phone' => ['required', 'string', 'max:50'],
            'password' => ['required', 'confirmed', 'min:8'],
            'gender' => ['nullable', 'in:male,female'],
            'date_of_birth' => ['nullable', 'date'],
            'occupation' => ['nullable', 'string', 'max:150'],
            'address' => ['nullable', 'string', 'max:1000'],
            'city' => ['nullable', 'string', 'max:100'],
            'state' => ['nullable', 'string', 'max:100'],
            'id_type' => ['nullable', 'string', 'max:100'],
            'id_number' => ['nullable', 'string', 'max:100'],
            'bvn' => ['nullable', 'digits:11'],
            'nin' => ['nullable', 'digits:11'],
            'guarantor_name' => ['nullable', 'string', 'max:255'],
            'guarantor_phone' => ['nullable', 'string', 'max:50'],
            'guarantor_address' => ['nullable', 'string', 'max:1000'],
            'guarantor_relationship' => ['nullable', 'string', 'max:100'],
        ]);

        [$user, $customer] = DB::transaction(function () use ($tenant, $validated, $branches): array {
            $branch = $branches->defaultBranch($tenant);

            $user = User::create([
                'tenant_id' => $tenant->id,
                'branch_id' => $branch?->id,
                'role' => User::ROLE_CUSTOMER,
                'name' => trim(collect([$validated['first_name'], $validated['middle_name'] ?? null, $validated['last_name']])->filter()->implode(' ')),
                'email' => $validated['email'],
                'phone' => $validated['phone'],
                'password' => $validated['password'],
                'status' => 'active',
            ]);

            $customer = Customer::withoutGlobalScopes()->create([
                'tenant_id' => $tenant->id,
                'branch_id' => $branch?->id,
                'user_id' => $user->id,
                'registration_source' => 'self_service',
                'account_number' => NumberGenerator::customerAccount($tenant),
                'first_name' => $validated['first_name'],
                'middle_name' => $validated['middle_name'] ?? null,
                'last_name' => $validated['last_name'],
                'email' => $validated['email'],
                'phone' => $validated['phone'],
                'gender' => $validated['gender'] ?? null,
                'date_of_birth' => $validated['date_of_birth'] ?? null,
                'occupation' => $validated['occupation'] ?? null,
                'address' => $validated['address'] ?? null,
                'city' => $validated['city'] ?? null,
                'state' => $validated['state'] ?? null,
                'id_type' => $validated['id_type'] ?? null,
                'id_number' => $validated['id_number'] ?? null,
                'bvn' => $validated['bvn'] ?? null,
                'nin' => $validated['nin'] ?? null,
                'guarantor_name' => $validated['guarantor_name'] ?? null,
                'guarantor_phone' => $validated['guarantor_phone'] ?? null,
                'guarantor_address' => $validated['guarantor_address'] ?? null,
                'guarantor_relationship' => $validated['guarantor_relationship'] ?? null,
                'status' => 'active',
                'kyc_status' => 'pending',
            ]);

            $savingsProduct = SavingsProduct::withoutGlobalScopes()
                ->where('tenant_id', $tenant->id)
                ->where('name', 'Regular Savings')
                ->first();

            SavingsAccount::withoutGlobalScopes()->create([
                'tenant_id' => $tenant->id,
                'customer_id' => $customer->id,
                'savings_product_id' => $savingsProduct?->id,
                'account_number' => NumberGenerator::make($tenant, $savingsProduct?->account_number_prefix ?: 'SAV', SavingsAccount::class, 'account_number'),
                'product_name' => 'Regular Savings',
                'product_type' => 'regular',
                'balance' => 0,
                'status' => 'active',
                'opened_at' => now(),
            ]);

            return [$user, $customer];
        });

        $kyc->apply($customer->fresh());

        Auth::login($user);
        $request->session()->regenerate();
        ActivityLogger::log('member_self_registered', $customer->fullName().' joined from the public tenant link.', $customer);

        return redirect()->route('member.dashboard')->with('status', 'Welcome. Your member portal is ready.');
    }

    public function login(Tenant $tenant): View|RedirectResponse
    {
        abort_unless($tenant->status === 'active', 404);

        if (auth()->check() && auth()->user()->tenant_id === $tenant->id && auth()->user()->role === User::ROLE_CUSTOMER) {
            return redirect()->route('member.dashboard');
        }

        return view('public.tenant-login', compact('tenant'));
    }

    public function authenticate(Request $request, Tenant $tenant): RedirectResponse
    {
        abort_unless($tenant->status === 'active', 404);

        $credentials = $request->validate([
            'email' => ['required', 'email'],
            'password' => ['required', 'string'],
        ]);

        $user = User::where('tenant_id', $tenant->id)
            ->where('role', User::ROLE_CUSTOMER)
            ->where('email', $credentials['email'])
            ->first();

        if (! $user || ! Hash::check($credentials['password'], $user->password) || $user->status !== 'active') {
            return back()->withErrors(['email' => 'The provided member login details are invalid.'])->onlyInput('email');
        }

        Auth::login($user, $request->boolean('remember'));
        $request->session()->regenerate();
        $user->forceFill(['last_login_at' => now()])->save();
        ActivityLogger::log('member_login', $user->name.' signed in from the public tenant link.');

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