<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\UserSetting;
use App\Models\SessionLog;
use App\Models\UserSession;
use App\Models\MessageTemplate;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Carbon\Carbon;

class AuthController extends Controller
{
    /**
     * Build service-control flags with admin/user/effective values.
     */
    private function buildServiceControls(User $user, UserSetting $settings): array
    {
        $adminSmsEnabled = (bool) $user->sms_service_enabled;
        $userSmsEnabled = (bool) ($settings->user_sms_service_enabled ?? true);
        $effectiveSmsEnabled = $adminSmsEnabled && $userSmsEnabled;

        $adminWhatsAppEnabled = (bool) ($settings->whatsapp_enabled ?? false);
        $userWhatsAppEnabled = (bool) ($settings->user_whatsapp_service_enabled ?? true);
        $effectiveWhatsAppEnabled = $adminWhatsAppEnabled && $userWhatsAppEnabled;

        return [
            'admin_sms_service_enabled' => $adminSmsEnabled,
            'user_sms_service_enabled' => $userSmsEnabled,
            'effective_sms_service_enabled' => $effectiveSmsEnabled,
            'sms_service_enabled' => $effectiveSmsEnabled,

            'admin_whatsapp_service_enabled' => $adminWhatsAppEnabled,
            'user_whatsapp_service_enabled' => $userWhatsAppEnabled,
            'effective_whatsapp_service_enabled' => $effectiveWhatsAppEnabled,
            'whatsapp_enabled' => $effectiveWhatsAppEnabled,
        ];
    }

    /**
     * Build complete settings payload.
     */
    private function buildSettingsPayload(User $user, UserSetting $settings): array
    {
        $serviceControls = $this->buildServiceControls($user, $settings);

        return array_merge($serviceControls, [
            'cooldown_hours' => $settings->cooldown_hours,
            'exclude_contacts' => $settings->exclude_contacts,
            'sync_enabled' => $settings->sync_enabled,
            'sync_interval_minutes' => $settings->sync_interval_minutes ?? 15,
            'reply_to_incoming' => $settings->reply_to_incoming ?? true,
            'reply_to_missed' => $settings->reply_to_missed ?? true,
            'reply_to_outgoing' => $settings->reply_to_outgoing ?? false,
            'promotion_on_incoming' => $settings->promotion_on_incoming ?? false,
            'promotion_on_outgoing' => $settings->promotion_on_outgoing ?? false,
            'promotion_on_missed' => $settings->promotion_on_missed ?? false,
            'whatsapp_reply_to_incoming' => $settings->whatsapp_reply_to_incoming ?? false,
            'whatsapp_reply_to_missed' => $settings->whatsapp_reply_to_missed ?? false,
            'whatsapp_reply_to_outgoing' => $settings->whatsapp_reply_to_outgoing ?? false,
            'whatsapp_promotion_on_incoming' => $settings->whatsapp_promotion_on_incoming ?? false,
            'whatsapp_promotion_on_outgoing' => $settings->whatsapp_promotion_on_outgoing ?? false,
            'whatsapp_promotion_on_missed' => $settings->whatsapp_promotion_on_missed ?? false,
            'whatsapp_mode' => $settings->whatsapp_mode ?? 'manual',
            'whatsapp_cooldown_hours' => $settings->whatsapp_cooldown_hours ?? 24,
            'preferred_channel' => $settings->preferred_channel ?? 'sms',
        ]);
    }

    /**
     * Login user - Users can ONLY be created by admin
     * 
     * SINGLE-SESSION ENFORCEMENT: Only one device can be logged in at a time.
     * If user already has an active session on a DIFFERENT device, login is blocked.
     * Same device re-login is allowed (session is refreshed).
     * Admin force-logout can clear the session to allow login on a new device.
     */
    public function login(Request $request)
    {
        Log::info('Login Request Received', [
            'has_phone' => $request->has('phone'),
            'has_password' => $request->has('password'),
            'device_id' => $request->device_id,
        ]);

        $validator = Validator::make($request->all(), [
            'phone' => 'required|string|max:20',
            'password' => 'required|string',
            'device_id' => 'required|string|max:255',
            'device_name' => 'nullable|string|max:255',
            'device_model' => 'nullable|string|max:255',
            'app_version' => 'nullable|string|max:50',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Validation error',
                'errors' => $validator->errors(),
            ], 422);
        }

        // Find user by phone number
        $user = User::where('phone', $request->phone)->first();

        if (!$user) {
            Log::warning('Login Failed - User not found', ['phone' => $request->phone]);
            return response()->json([
                'success' => false,
                'message' => 'Invalid credentials. Please contact administrator.',
                'error_code' => 'USER_NOT_FOUND',
            ], 401);
        }

        // Check if user account is active
        if (!$user->is_active) {
            Log::warning('Login Failed - Account inactive', ['user_id' => $user->id]);
            return response()->json([
                'success' => false,
                'message' => 'Your account is inactive. Please contact administrator.',
                'error_code' => 'ACCOUNT_INACTIVE',
            ], 403);
        }

        // Check if user can login (approval status + org subscription)
        if (!$user->canLogin()) {
            $reason = $user->getLoginDenialReason() ?? 'Login not permitted.';
            Log::warning('Login Failed - canLogin check', ['user_id' => $user->id, 'reason' => $reason]);
            return response()->json([
                'success' => false,
                'message' => $reason,
                'error_code' => 'LOGIN_DENIED',
            ], 403);
        }

        // Verify password
        if (!Hash::check($request->password, $user->password)) {
            Log::warning('Login Failed - Invalid password', ['user_id' => $user->id]);
            return response()->json([
                'success' => false,
                'message' => 'Invalid credentials.',
                'error_code' => 'INVALID_PASSWORD',
            ], 401);
        }

        // ====== SINGLE-SESSION ENFORCEMENT ======
        // Check if user has an active session on a DIFFERENT device
        $activeSessions = UserSession::getActiveSessionsForUser($user->id);
        $otherDeviceSession = $activeSessions->first(function ($session) use ($request) {
            return $session->device_id !== $request->device_id;
        });

        if ($otherDeviceSession) {
            Log::warning('Login Blocked - Active session on another device', [
                'user_id' => $user->id,
                'current_device' => $request->device_id,
                'active_device' => $otherDeviceSession->device_id,
                'active_device_name' => $otherDeviceSession->device_name,
            ]);
            return response()->json([
                'success' => false,
                'message' => 'You are already logged in on another device ('
                    . ($otherDeviceSession->device_name ?? $otherDeviceSession->device_model ?? 'Unknown Device')
                    . '). Please logout from that device first, or contact your administrator to force logout.',
                'error_code' => 'DEVICE_CONFLICT',
                'data' => [
                    'active_device_name' => $otherDeviceSession->device_name,
                    'active_device_model' => $otherDeviceSession->device_model,
                    'last_active_at' => $otherDeviceSession->last_active_at?->toIso8601String(),
                ],
            ], 409);
        }

        // Create session for this device (same device re-login replaces token)
        $sessionToken = Str::random(64);
        $tokenExpiry = Carbon::now()->addDays(30);

        // Create or update session for this device
        $session = UserSession::createSession(
            userId: $user->id,
            deviceId: $request->device_id,
            token: $sessionToken,
            deviceName: $request->device_name,
            deviceModel: $request->device_model,
            appVersion: $request->app_version,
            expiresInDays: 30
        );

        // Update user's last active and clear any force_logout flag
        $user->update([
            'api_token' => hash('sha256', $sessionToken),
            'last_active_at' => now(),
            'force_logout' => false,
            'force_logout_reason' => null,
        ]);

        // Get count of active sessions for this user (should be 1 with single-session)
        $activeSessionsCount = UserSession::getActiveSessionsForUser($user->id)->count();

        // Log the login
        SessionLog::logLogin($user, [
            'device_id' => $request->device_id,
            'device_name' => $request->device_name,
            'device_model' => $request->device_model,
            'app_version' => $request->app_version,
        ], $request->ip());

        // Get user settings
        $settings = $user->getOrCreateSettings();

        // Get active templates from user's organization (client)
        $templates = $user->client_id
            ? MessageTemplate::where('client_id', $user->client_id)
            ->where('is_active', true)
            ->whereIn('channel', ['sms', 'whatsapp'])
            ->orderBy('priority')
            ->get()
            ->map(fn($t) => $t->toApiResponse())
            : collect([]);

        // Load organization info
        $client = $user->client_id ? $user->client : null;
        $settingsPayload = $this->buildSettingsPayload($user, $settings);

        Log::info('Login Successful - Single session', [
            'user_id' => $user->id,
            'device_id' => $request->device_id,
            'session_id' => $session->id,
            'active_sessions' => $activeSessionsCount,
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Login successful',
            'data' => [
                'user' => [
                    'id' => $user->id,
                    'name' => $user->name,
                    'email' => $user->email,
                    'phone' => $user->phone,
                ],
                'organization' => $client ? [
                    'id' => $client->id,
                    'name' => $client->name,
                ] : null,
                'token' => $sessionToken,
                'token_expires_at' => $tokenExpiry->toIso8601String(),
                'session_id' => $session->id,
                'active_sessions_count' => $activeSessionsCount,
                'sms_service_enabled' => $settingsPayload['sms_service_enabled'],
                'admin_sms_service_enabled' => $settingsPayload['admin_sms_service_enabled'],
                'user_sms_service_enabled' => $settingsPayload['user_sms_service_enabled'],
                'effective_sms_service_enabled' => $settingsPayload['effective_sms_service_enabled'],
                'whatsapp_enabled' => $settingsPayload['whatsapp_enabled'],
                'admin_whatsapp_service_enabled' => $settingsPayload['admin_whatsapp_service_enabled'],
                'user_whatsapp_service_enabled' => $settingsPayload['user_whatsapp_service_enabled'],
                'effective_whatsapp_service_enabled' => $settingsPayload['effective_whatsapp_service_enabled'],
                'promotions_enabled' => $user->promotions_enabled,
                'settings' => $settingsPayload,
                'templates' => $templates,
            ],
        ]);
    }

    /**
     * Validate session - Called on app launch and periodically
     * 
     * SINGLE-SESSION: Each user has exactly one active session.
     * Session is validated via user_sessions table.
     * Returns force_logout_reason for differentiated error messages.
     */
    public function validateSession(Request $request)
    {
        $user = $request->user();
        $session = $request->get('user_session'); // Set by middleware

        if (!$user || !$session) {
            return response()->json([
                'success' => false,
                'message' => 'Session invalid',
                'error_code' => 'SESSION_INVALID',
                'force_logout' => true,
            ], 401);
        }

        // Check force logout flag (admin force logout)
        if ($user->force_logout) {
            $reason = $user->force_logout_reason ?? 'admin_force_logout';
            $message = match ($reason) {
                'admin_force_logout' => 'Your session has been terminated by administrator.',
                'password_reset' => 'Your password was reset by administrator. Please login with your new password.',
                'account_deactivated' => 'Your account has been deactivated by administrator.',
                default => 'Your session has been terminated.',
            };
            $session->invalidate();
            return response()->json([
                'success' => false,
                'message' => $message,
                'error_code' => 'FORCE_LOGOUT',
                'force_logout' => true,
                'force_logout_reason' => $reason,
            ], 401);
        }

        // Check if account is still active
        if (!$user->is_active) {
            return response()->json([
                'success' => false,
                'message' => 'Your account has been deactivated.',
                'error_code' => 'ACCOUNT_INACTIVE',
                'force_logout' => true,
            ], 403);
        }

        // Check organization subscription status
        if ($user->client_id && $user->client) {
            if (!$user->client->hasActiveSubscription()) {
                $session->invalidate();
                $reason = !$user->client->is_active
                    ? 'Your organization has been disabled. Please contact support.'
                    : 'Your organization\'s subscription has expired. Please contact your administrator.';
                return response()->json([
                    'success' => false,
                    'message' => $reason,
                    'error_code' => 'ORG_INACTIVE',
                    'force_logout' => true,
                ], 403);
            }
        }

        // Update last active timestamp
        $user->touchLastActive();
        $session->touch(); // Update session last_active_at

        // Get latest settings
        $settings = $user->getOrCreateSettings();

        // Load organization info for app
        $client = $user->client_id ? $user->client : null;
        $settingsPayload = $this->buildSettingsPayload($user, $settings);

        return response()->json([
            'success' => true,
            'message' => 'Session valid',
            'data' => [
                'session_id' => $session->id,
                'device_id' => $session->device_id,
                'organization' => $client ? [
                    'id' => $client->id,
                    'name' => $client->name,
                    'subscription_status' => $client->getSubscriptionStatusLabel(),
                ] : null,
                'sms_service_enabled' => $settingsPayload['sms_service_enabled'],
                'admin_sms_service_enabled' => $settingsPayload['admin_sms_service_enabled'],
                'user_sms_service_enabled' => $settingsPayload['user_sms_service_enabled'],
                'effective_sms_service_enabled' => $settingsPayload['effective_sms_service_enabled'],
                'whatsapp_enabled' => $settingsPayload['whatsapp_enabled'],
                'admin_whatsapp_service_enabled' => $settingsPayload['admin_whatsapp_service_enabled'],
                'user_whatsapp_service_enabled' => $settingsPayload['user_whatsapp_service_enabled'],
                'effective_whatsapp_service_enabled' => $settingsPayload['effective_whatsapp_service_enabled'],
                'promotions_enabled' => $user->promotions_enabled,
                'settings' => $settingsPayload,
            ],
        ]);
    }

    /**
     * Logout user - Invalidates the session so user can login on another device.
     * 
     * SINGLE-SESSION: After logout, user can login on any device.
     */
    public function logout(Request $request)
    {
        $user = $request->user();
        $session = $request->get('user_session'); // Set by middleware
        $deviceId = $request->header('X-Device-ID');

        // Log the logout
        SessionLog::logLogout($user, $deviceId, $request->ip());

        // Invalidate only THIS device's session
        if ($session) {
            $session->invalidate();
        }

        Log::info('User logged out - Single session', [
            'user_id' => $user->id,
            'session_id' => $session?->id,
            'device_id' => $deviceId,
        ]);

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

    /**
     * Get all active sessions for the user
     */
    public function getSessions(Request $request)
    {
        $user = $request->user();
        $currentSession = $request->get('user_session');

        $sessions = UserSession::getActiveSessionsForUser($user->id)
            ->map(function ($session) use ($currentSession) {
                return [
                    'id' => $session->id,
                    'device_id' => $session->device_id,
                    'device_name' => $session->device_name,
                    'device_model' => $session->device_model,
                    'last_active_at' => $session->last_active_at?->toIso8601String(),
                    'is_current' => $currentSession && $session->id === $currentSession->id,
                ];
            });

        return response()->json([
            'success' => true,
            'data' => [
                'sessions' => $sessions,
                'total' => $sessions->count(),
            ],
        ]);
    }

    /**
     * Logout a specific device
     */
    public function logoutDevice(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'session_id' => 'required|integer',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Validation error',
                'errors' => $validator->errors(),
            ], 422);
        }

        $user = $request->user();
        $session = UserSession::where('id', $request->session_id)
            ->where('user_id', $user->id)
            ->first();

        if (!$session) {
            return response()->json([
                'success' => false,
                'message' => 'Session not found',
            ], 404);
        }

        $session->invalidate();

        return response()->json([
            'success' => true,
            'message' => 'Device logged out successfully',
        ]);
    }

    /**
     * Logout all other devices except current
     */
    public function logoutAllOtherDevices(Request $request)
    {
        $user = $request->user();
        $currentSession = $request->get('user_session');

        $count = UserSession::invalidateAllExcept($user->id, $currentSession->id);

        return response()->json([
            'success' => true,
            'message' => "Logged out $count other device(s)",
            'data' => [
                'devices_logged_out' => $count,
            ],
        ]);
    }

    /**
     * Get authenticated user profile with full settings.
     */
    public function profile(Request $request)
    {
        $user = $request->user();
        $settings = $user->getOrCreateSettings();
        $stats = $user->getStats();

        // Get active templates from user's organization
        $templates = $user->client_id
            ? MessageTemplate::where('client_id', $user->client_id)
            ->where('is_active', true)
            ->whereIn('channel', ['sms', 'whatsapp'])
            ->orderBy('priority')
            ->get()
            ->map(fn($t) => $t->toApiResponse())
            : collect([]);

        // Load organization info
        $client = $user->client_id ? $user->client : null;
        $settingsPayload = $this->buildSettingsPayload($user, $settings);

        return response()->json([
            'success' => true,
            'data' => [
                'user' => [
                    'id' => $user->id,
                    'name' => $user->name,
                    'email' => $user->email,
                    'phone' => $user->phone,
                    'device_id' => $user->session_device_id,
                    'is_active' => $user->is_active,
                    'sms_service_enabled' => $settingsPayload['sms_service_enabled'],
                    'admin_sms_service_enabled' => $settingsPayload['admin_sms_service_enabled'],
                    'user_sms_service_enabled' => $settingsPayload['user_sms_service_enabled'],
                    'effective_sms_service_enabled' => $settingsPayload['effective_sms_service_enabled'],
                    'whatsapp_enabled' => $settingsPayload['whatsapp_enabled'],
                    'admin_whatsapp_service_enabled' => $settingsPayload['admin_whatsapp_service_enabled'],
                    'user_whatsapp_service_enabled' => $settingsPayload['user_whatsapp_service_enabled'],
                    'effective_whatsapp_service_enabled' => $settingsPayload['effective_whatsapp_service_enabled'],
                    'promotions_enabled' => $user->promotions_enabled,
                    'last_active_at' => $user->last_active_at?->toIso8601String(),
                ],
                'organization' => $client ? [
                    'id' => $client->id,
                    'name' => $client->name,
                ] : null,
                'settings' => $settingsPayload,
                'stats' => $stats,
                'templates' => $templates,
            ],
        ]);
    }

    /**
     * Register is DISABLED - Users are created only by admin
     */
    public function register(Request $request)
    {
        return response()->json([
            'success' => false,
            'message' => 'Registration is disabled. Please contact administrator to create an account.',
            'error_code' => 'REGISTRATION_DISABLED',
        ], 403);
    }

    /**
     * Update user profile - Limited fields only
     */
    public function updateProfile(Request $request)
    {
        $user = $request->user();

        $validator = Validator::make($request->all(), [
            'name' => 'sometimes|string|max:255',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Validation error',
                'errors' => $validator->errors(),
            ], 422);
        }

        // Only allow name update, phone is controlled by admin
        $user->update($request->only(['name']));

        return response()->json([
            'success' => true,
            'message' => 'Profile updated successfully',
            'data' => [
                'user' => [
                    'id' => $user->id,
                    'name' => $user->name,
                    'email' => $user->email,
                    'phone' => $user->phone,
                ],
            ],
        ]);
    }
}
