import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:on_field_work/controller/my_controller.dart';
import 'package:on_field_work/helpers/services/api_service.dart';
import 'package:on_field_work/helpers/services/app_logger.dart';
import 'package:on_field_work/helpers/widgets/my_form_validator.dart';
import 'package:on_field_work/helpers/widgets/my_snackbar.dart';
import 'package:flutter_contacts/flutter_contacts.dart';
import 'package:permission_handler/permission_handler.dart';

enum Gender {
  male,
  female,
  other;

  const Gender();
}

class AddEmployeeController extends MyController {
  Map<String, dynamic>? editingEmployeeData;

  // State
  final MyFormValidator basicValidator = MyFormValidator();
  final List<PlatformFile> files = [];
  final List<String> categories = [];

  Gender? selectedGender;
  List<Map<String, dynamic>> roles = [];
  String? selectedRoleId;
  String selectedCountryCode = '+91';
  bool showOnline = true;
  DateTime? joiningDate;
  String? selectedOrganizationId;
  RxString selectedOrganizationName = RxString('');

  @override
  void onInit() {
    super.onInit();
    logSafe('Initializing AddEmployeeController...');
    _initializeFields();
    fetchRoles();

    if (editingEmployeeData != null) {
      prefillFields();
    }
  }

  void _initializeFields() {
    basicValidator.addField(
      'first_name',
      label: 'First Name',
      required: true,
      controller: TextEditingController(),
    );
    basicValidator.addField(
      'phone_number',
      label: 'Phone Number',
      required: true,
      controller: TextEditingController(),
    );
    basicValidator.addField(
      'last_name',
      label: 'Last Name',
      required: true,
      controller: TextEditingController(),
    );
    // Email is optional in controller; UI enforces when application access is checked
    basicValidator.addField(
      'email',
      label: 'Email',
      required: false,
      controller: TextEditingController(),
    );

    logSafe('Fields initialized for first_name, phone_number, last_name, email.');
  }

  // Prefill fields in edit mode
  void prefillFields() {
    logSafe('Prefilling data for editing...');
    basicValidator.getController('first_name')?.text =
        editingEmployeeData?['first_name'] ?? '';
    basicValidator.getController('last_name')?.text =
        editingEmployeeData?['last_name'] ?? '';
    basicValidator.getController('phone_number')?.text =
        editingEmployeeData?['phone_number'] ?? '';

    selectedGender = editingEmployeeData?['gender'] != null
        ? Gender.values.firstWhereOrNull((g) => g.name == editingEmployeeData!['gender'])
        : null;

    basicValidator.getController('email')?.text =
        editingEmployeeData?['email'] ?? '';

    selectedRoleId = editingEmployeeData?['job_role_id'];

    if (editingEmployeeData?['joining_date'] != null) {
      joiningDate = DateTime.tryParse(editingEmployeeData!['joining_date']);
    }

    update();
  }

  void setJoiningDate(DateTime date) {
    joiningDate = date;
    logSafe('Joining date selected: $date');
    update();
  }

  void onGenderSelected(Gender? gender) {
    selectedGender = gender;
    logSafe('Gender selected: ${gender?.name}');
    update();
  }

  Future<void> fetchRoles() async {
    logSafe('Fetching roles...');
    try {
      final result = await ApiService.getRoles();
      if (result != null) {
        roles = List<Map<String, dynamic>>.from(result);
        logSafe('Roles fetched successfully.');
        update();
      } else {
        logSafe('Failed to fetch roles: null result', level: LogLevel.error);
      }
    } catch (e, st) {
      logSafe('Error fetching roles', level: LogLevel.error, error: e, stackTrace: st);
    }
  }

  void onRoleSelected(String? roleId) {
    selectedRoleId = roleId;
    logSafe('Role selected: $roleId');
    update();
  }

  // Create or update employee
  Future<Map<String, dynamic>?> createOrUpdateEmployee({
    String? email,
    bool hasApplicationAccess = false,
  }) async {
    logSafe(editingEmployeeData != null
        ? 'Starting employee update...'
        : 'Starting employee creation...');

    if (selectedGender == null || selectedRoleId == null) {
      showAppSnackbar(
        title: 'Missing Fields',
        message: 'Please select both Gender and Role.',
        type: SnackbarType.warning,
      );
      return null;
    }

    final firstName = basicValidator.getController('first_name')?.text.trim();
    final lastName = basicValidator.getController('last_name')?.text.trim();
    final phoneNumber = basicValidator.getController('phone_number')?.text.trim();

    try {
      // sanitize orgId before sending
      final String? orgId = (selectedOrganizationId != null &&
              selectedOrganizationId!.trim().isNotEmpty)
          ? selectedOrganizationId
          : null;

      final response = await ApiService.createEmployee(
        id: editingEmployeeData?['id'],
        firstName: firstName!,
        lastName: lastName!,
        phoneNumber: phoneNumber!,
        gender: selectedGender!.name,
        jobRoleId: selectedRoleId!,
        joiningDate: joiningDate?.toIso8601String() ?? '',
        organizationId: orgId,
        email: email,
        hasApplicationAccess: hasApplicationAccess,
      );

      logSafe('Response: $response');

      if (response != null && response['success'] == true) {
        showAppSnackbar(
          title: 'Success',
          message: editingEmployeeData != null
              ? 'Employee updated successfully!'
              : 'Employee created successfully!',
          type: SnackbarType.success,
        );
        return response;
      } else {
        logSafe('Failed operation', level: LogLevel.error);
      }
    } catch (e, st) {
      logSafe('Error creating/updating employee',
          level: LogLevel.error, error: e, stackTrace: st);
    }

    showAppSnackbar(
      title: 'Error',
      message: 'Failed to save employee.',
      type: SnackbarType.error,
    );
    return null;
  }

  Future<bool> _checkAndRequestContactsPermission() async {
    final status = await Permission.contacts.request();

    if (status.isGranted) return true;

    if (status.isPermanentlyDenied) {
      await openAppSettings();
    }

    showAppSnackbar(
      title: 'Permission Required',
      message: 'Please allow Contacts permission from settings to pick a contact.',
      type: SnackbarType.warning,
    );
    return false;
  }

  Future<void> pickContact(BuildContext context) async {
    final permissionGranted = await _checkAndRequestContactsPermission();
    if (!permissionGranted) return;

    try {
      final picked = await FlutterContacts.openExternalPick();
      if (picked == null) return;

      final contact =
          await FlutterContacts.getContact(picked.id, withProperties: true);
      if (contact == null) {
        showAppSnackbar(
          title: 'Error',
          message: 'Failed to load contact details.',
          type: SnackbarType.error,
        );
        return;
      }

      if (contact.phones.isEmpty) {
        showAppSnackbar(
          title: 'No Phone Number',
          message: 'Selected contact has no phone number.',
          type: SnackbarType.warning,
        );
        return;
      }

      final indiaPhones = contact.phones.where((p) {
        final normalized = p.number.replaceAll(RegExp(r'[^0-9+]'), '');
        return normalized.startsWith('+91') ||
            RegExp(r'^\d{10}$').hasMatch(normalized);
      }).toList();

      if (indiaPhones.isEmpty) {
        showAppSnackbar(
          title: 'No Indian Number',
          message: 'Selected contact has no Indian (+91) phone number.',
          type: SnackbarType.warning,
        );
        return;
      }

      String? selectedPhone;
      if (indiaPhones.length == 1) {
        selectedPhone = indiaPhones.first.number;
      } else {
        selectedPhone = await showDialog<String>(
          context: context,
          builder: (ctx) => AlertDialog(
            title: const Text('Choose an Indian number'),
            content: Column(
              mainAxisSize: MainAxisSize.min,
              children: indiaPhones
                  .map(
                    (p) => ListTile(
                      title: Text(p.number),
                      onTap: () => Navigator.of(ctx).pop(p.number),
                    ),
                  )
                  .toList(),
            ),
          ),
        );
        if (selectedPhone == null) return;
      }

      final normalizedPhone = selectedPhone.replaceAll(RegExp(r'[^0-9]'), '');
      final phoneWithoutCountryCode = normalizedPhone.length > 10
          ? normalizedPhone.substring(normalizedPhone.length - 10)
          : normalizedPhone;

      basicValidator.getController('phone_number')?.text =
          phoneWithoutCountryCode;
      update();
    } catch (e, st) {
      logSafe('Error fetching contacts',
          level: LogLevel.error, error: e, stackTrace: st);
      showAppSnackbar(
        title: 'Error',
        message: 'Failed to fetch contacts.',
        type: SnackbarType.error,
      );
    }
  }
}
