import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import 'package:html/parser.dart' as html_parser;
import 'package:inventory_system/services/api_service.dart';
import 'package:inventory_system/services/session_manager.dart';

class AuthService {
  Future<Map<String, dynamic>> signIn({
    required String usernameOrEmail,
    required String password,
  }) async {
    if (usernameOrEmail.toLowerCase() == 'admin@pstw.com.my') {
      return _performAdminWebLogin(usernameOrEmail, password);
    } else {
      return _performLdapApiLogin(usernameOrEmail, password);
    }
  }

  Future<Map<String, dynamic>> _performLdapApiLogin(
      String username, String password) async {
    final Uri loginUri = Uri.parse('${ApiService.baseUrl}/IdentityAPI/LdapLogin');
    final loginHeaders = {'Content-Type': 'application/json; charset=UTF-8'};
    final loginBody = jsonEncode({'UserName': username, 'Password': password});

    try {
      final response = await http.post(loginUri, headers: loginHeaders, body: loginBody);

      if (response.statusCode != 200) {
        return _handleLdapError(response);
      }

      final String? sessionCookie = response.headers['set-cookie'];
      if (sessionCookie == null) {
        return {'success': false, 'message': 'Login succeeded, but failed to start a session.'};
      }
      SessionManager.instance.setCookie(sessionCookie);

      return await _fetchLdapUserDetails(sessionCookie, username);

    } on TimeoutException {
        return {'success': false, 'message': 'The connection timed out. Please try again.'};
    } on SocketException {
        return {'success': false, 'message': 'Could not connect to the server. Please check your network.'};
    } catch (e) {
        debugPrint('An unexpected error occurred during LDAP login: $e');
        return {'success': false, 'message': 'An unexpected error occurred.'};
    }
  }

  Future<Map<String, dynamic>> fetchUserProfile() async {
    final String? sessionCookie = SessionManager.instance.getCookie();
    if (sessionCookie == null) {
      return {'success': false, 'message': 'No active session found.'};
    }

    final Uri userInfoUri = Uri.parse('${ApiService.baseUrl}/IdentityAPI/GetUserInformation');
    final headers = {'Cookie': sessionCookie};

    try {
      final response = await http.post(userInfoUri, headers: headers);

      if (response.statusCode == 200) {
        final userInfoResponse = jsonDecode(response.body);
        final Map<String, dynamic>? userData = userInfoResponse['userInfo'];

        if (userData == null) {
          return {'success': false, 'message': 'User profile data is missing from the API response.'};
        }

        return {
          'success': true,
          'data': userData // Return raw user data as requested for display
        };
      } else {
        return {'success': false, 'message': 'Failed to retrieve user profile. Status: ${response.statusCode}'};
      }
    } catch (e) {
      debugPrint('Error fetching user profile: $e');
      return {'success': false, 'message': 'Error fetching user details.'};
    }
  }

  Future<Map<String, dynamic>> _fetchLdapUserDetails(String sessionCookie, String username) async {
    final Uri userInfoUri = Uri.parse('${ApiService.baseUrl}/IdentityAPI/GetUserInformation');
    final headers = {'Cookie': sessionCookie};

    try {
      final response = await http.post(userInfoUri, headers: headers);

      if (response.statusCode == 200) {
        final userInfoResponse = jsonDecode(response.body);
        final Map<String, dynamic>? userData = userInfoResponse['userInfo'];

        if (userData == null) {
          return {'success': false, 'message': 'User profile data is missing from the API response.'};
        }

        final List<dynamic> roles = userData['role'] ?? [];
        final bool isInventoryMaster = roles.contains('Inventory Master');
        final bool isSuperAdmin = roles.contains('Super Admin');

        final Map<String, dynamic> sessionData = Map<String, dynamic>.from(userData);
        sessionData['fullName'] = username;
        sessionData['isAdmin'] = isInventoryMaster || isSuperAdmin;
        sessionData['isInventoryMaster'] = isInventoryMaster;
        sessionData['isSuperAdmin'] = isSuperAdmin;
        sessionData['role'] = roles;
        
        return {
          'success': true,
          'data': sessionData
        };
      } else {
        return {'success': false, 'message': 'Logged in, but failed to retrieve user profile.'};
      }
    } catch (e) {
        return {'success': false, 'message': 'Error fetching user details after login.'};
    }
  }

  Map<String, dynamic> _handleLdapError(http.Response response) {
    try {
      final errorData = jsonDecode(response.body);
      String errorMessage = errorData['message'] ?? 'An unknown error occurred';

      if (errorMessage.toLowerCase().contains('was not found')) {
        return {'success': false, 'message': 'Wrong username or email.'};
      } else if (errorMessage.toLowerCase().contains('incorrect password.')) {
        return {'success': false, 'message': 'Wrong password.'};
      } else {
        return {'success': false, 'message': errorMessage};
      }
    } catch (e) {
      return {'success': false, 'message': 'Login failed with status: ${response.statusCode}'};
    }
  }

  Future<Map<String, dynamic>> _performAdminWebLogin(
      String email, String password) async {
    final Uri loginUri = Uri.parse('${ApiService.baseUrl}/Identity/Account/Login');

    try {
      final getResponse = await http.get(loginUri);
      final String? sessionCookie = getResponse.headers['set-cookie'];
      final document = html_parser.parse(getResponse.body);
      final token = document.querySelector('input[name="__RequestVerificationToken"]')?.attributes['value'];

      if (sessionCookie == null || token == null) {
        return {'success': false, 'message': 'Failed to prepare a secure login session.'};
      }
      
      SessionManager.instance.setCookie(sessionCookie);

      final postResponse = await http.post(
        loginUri,
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          'Cookie': sessionCookie,
        },
        body: {
          'Email': email,
          'Password': password,
          'RememberMe': 'false',
          '__RequestVerificationToken': token,
        },
      );

      if (postResponse.statusCode == 302) {
        // After a successful login, the server issues a new, authenticated cookie.
        // We must capture and save this new cookie from the POST response.
        final String? newSessionCookie = postResponse.headers['set-cookie'];
        if (newSessionCookie != null) {
          SessionManager.instance.setCookie(newSessionCookie);
        }
        
        return {
          'success': true,
          'data': {
            'fullName': 'Super Admin',
            'isAdmin': true,
            'isInventoryMaster': false,
            'isSuperAdmin': true,
            'role': ['Super Admin'],
          }
        };
      } else {
        return {'success': false, 'message': 'Admin login failed. Please check credentials.'};
      }
    } catch (e) {
        debugPrint('An unexpected error occurred during Admin login: $e');
        return {'success': false, 'message': 'An unexpected error occurred.'};
    }
  }
}
