<?php

namespace App\Http\Controllers\API;

use App\Http\Controllers\Controller;
use App\Models\Tenant;
use App\Models\User;
use App\Models\DeviceSession;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;

class AuthController extends Controller
{
    /**
     * POST /api/auth/login
     *
     * Validates credentials, enforces single-device session,
     * returns Sanctum token + user profile.
     */
    public function login(Request $request)
    {
        $validated = $request->validate([
            'email'     => 'required|email',
            'password'  => 'required|string',
            'device_id' => 'nullable|string|max:128',
        ]);

        $user = User::where('email', $validated['email'])->first();

        if (!$user || !Hash::check($validated['password'], $user->password)) {
            throw ValidationException::withMessages([
                'email' => ['These credentials do not match our records.'],
            ]);
        }

        // Check tenant subscription (skip for super_admin)
        if (!$user->isSuperAdmin() && $user->tenant) {
            $tenant = $user->tenant;
            if ($tenant->isSuspended()) {
                return response()->json([
                    'error'   => 'Subscription expired or inactive',
                    'reason'  => 'suspended',
                    'message' => 'Your account has been suspended.',
                ], 402);
            }
        }

        // Device session enforcement
        $deviceId = $validated['device_id'] ?? $this->generateDeviceId($request);

        if (!$user->isSuperAdmin()) {
            $limits = $user->tenant?->getPlanLimits() ?? [];
            $deviceLimit = $limits['device_limit'] ?? 1;

            // Revoke previous sessions if over limit
            $activeSessions = DeviceSession::where('user_id', $user->id)
                ->where('is_active', true)
                ->where('device_id', '!=', $deviceId)
                ->get();

            if ($activeSessions->count() >= $deviceLimit) {
                // Revoke oldest sessions and their tokens
                $user->revokeAllOtherSessions($deviceId);
            }
        }

        // Create device session
        DeviceSession::updateOrCreate(
            ['user_id' => $user->id, 'device_id' => $deviceId],
            [
                'ip_address'  => $request->ip(),
                'device_info' => [
                    'user_agent' => $request->userAgent(),
                    'ip'         => $request->ip(),
                ],
                'is_active'   => true,
                'last_seen_at'=> now(),
            ]
        );

        // Revoke old tokens for this device and create new one
        $user->tokens()->where('name', $deviceId)->delete();
        $token = $user->createToken($deviceId)->plainTextToken;

        return response()->json([
            'token' => $token,
            'user'  => $this->formatUser($user),
        ]);
    }

    /**
     * POST /api/auth/register
     *
     * Creates a new Tenant + admin User.
     * Starts on free plan immediately (no lifetime access warning needed).
     */
    public function register(Request $request)
    {
        $validated = $request->validate([
            'company_name'          => 'required|string|max:255',
            'email'                 => 'required|email|unique:users,email',
            'password'              => 'required|string|min:8|confirmed',
            'password_confirmation' => 'required|string',
        ]);

        DB::beginTransaction();
        try {
            // Create tenant
            $tenant = Tenant::create([
                'name'               => $validated['company_name'],
                'plan'               => Tenant::PLAN_FREE,
                'status'             => Tenant::STATUS_ACTIVE,
                'subscription_start' => now(),
                'subscription_end'   => now()->addDays(14), // 14-day free trial
                'default_country'    => 'PK',
            ]);

            // Create admin user for this tenant
            $user = User::create([
                'name'      => $validated['company_name'],
                'email'     => $validated['email'],
                'password'  => Hash::make($validated['password']),
                'tenant_id' => $tenant->id,
            ]);
            $user->assignRole('admin');

            DB::commit();

            $token = $user->createToken('register')->plainTextToken;

            return response()->json([
                'token' => $token,
                'user'  => $this->formatUser($user->fresh('tenant')),
            ], 201);

        } catch (\Throwable $e) {
            DB::rollBack();
            throw $e;
        }
    }

    /**
     * POST /api/auth/logout
     */
    public function logout(Request $request)
    {
        $deviceId = $request->input('_device_id') ?? 'unknown';

        // Deactivate device session
        DeviceSession::where('user_id', $request->user()->id)
            ->where('device_id', $deviceId)
            ->update(['is_active' => false]);

        // Revoke current token
        $request->user()->currentAccessToken()->delete();

        return response()->json(['message' => 'Logged out successfully.']);
    }

    /**
     * GET /api/auth/me
     */
    public function me(Request $request)
    {
        return response()->json($this->formatUser($request->user()->load('tenant')));
    }

    // ── Private helpers ────────────────────────────────────────────────────

    private function formatUser(User $user): array
    {
        return [
            'id'                  => $user->id,
            'name'                => $user->name,
            'email'               => $user->email,
            'role'                => $user->getRoleNames()->first() ?? 'user',
            'tenant_id'           => $user->tenant_id,
            'tenant_name'         => $user->tenant?->name,
            'plan'                => $user->tenant?->plan,
            'subscription_status' => $user->tenant?->status,
        ];
    }

    private function generateDeviceId(Request $request): string
    {
        return 'fp_' . substr(hash('sha256', $request->userAgent() . '|' . $request->ip()), 0, 32);
    }
}
