import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../../models/office.dart';
import '../../providers/auth_provider.dart' show sessionProvider;
import '../../providers/profile_provider.dart';
import '../../providers/tickets_provider.dart';
import '../../providers/user_offices_provider.dart';
import '../../widgets/multi_select_picker.dart';
import '../../widgets/responsive_body.dart';

class ProfileScreen extends ConsumerStatefulWidget {
  const ProfileScreen({super.key});

  @override
  ConsumerState<ProfileScreen> createState() => _ProfileScreenState();
}

class _ProfileScreenState extends ConsumerState<ProfileScreen> {
  final _detailsKey = GlobalKey<FormState>();
  final _passwordKey = GlobalKey<FormState>();
  final _fullNameController = TextEditingController();
  final _newPasswordController = TextEditingController();
  final _confirmPasswordController = TextEditingController();
  List<String> _selectedOfficeIds = [];
  bool _savingDetails = false;
  bool _changingPassword = false;
  bool _savingOffices = false;

  @override
  void dispose() {
    _fullNameController.dispose();
    _newPasswordController.dispose();
    _confirmPasswordController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final profileAsync = ref.watch(currentProfileProvider);
    final officesAsync = ref.watch(officesProvider);
    final userOfficesAsync = ref.watch(userOfficesProvider);
    final userId = ref.watch(currentUserIdProvider);
    final session = ref.watch(sessionProvider);

    // Populate controllers from profile stream (if not editing)
    profileAsync.whenData((p) {
      final name = p?.fullName ?? '';
      if (_fullNameController.text != name) {
        _fullNameController.text = name;
      }
    });

    // Populate selected offices from userOfficesProvider
    final assignedOfficeIds =
        userOfficesAsync.valueOrNull
            ?.where((u) => u.userId == userId)
            .map((u) => u.officeId)
            .toList() ??
        [];
    if (_selectedOfficeIds.isEmpty) {
      _selectedOfficeIds = List<String>.from(assignedOfficeIds);
    }

    return ResponsiveBody(
      child: SingleChildScrollView(
        padding: const EdgeInsets.only(top: 16, bottom: 32),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('My Profile', style: Theme.of(context).textTheme.titleLarge),
            const SizedBox(height: 12),

            // Details Card
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Form(
                  key: _detailsKey,
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        'Account details',
                        style: Theme.of(context).textTheme.titleMedium,
                      ),
                      const SizedBox(height: 12),
                      // Email (read-only)
                      TextFormField(
                        initialValue: session?.user.email ?? '',
                        decoration: const InputDecoration(labelText: 'Email'),
                        readOnly: true,
                      ),
                      const SizedBox(height: 12),
                      TextFormField(
                        controller: _fullNameController,
                        decoration: const InputDecoration(
                          labelText: 'Full name',
                        ),
                        validator: (v) => (v ?? '').trim().isEmpty
                            ? 'Full name is required'
                            : null,
                      ),
                      const SizedBox(height: 12),
                      Row(
                        children: [
                          ElevatedButton(
                            onPressed: _savingDetails ? null : _onSaveDetails,
                            child: Text(
                              _savingDetails ? 'Saving...' : 'Save details',
                            ),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ),
            ),

            const SizedBox(height: 12),

            // Change password Card
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Form(
                  key: _passwordKey,
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        'Password',
                        style: Theme.of(context).textTheme.titleMedium,
                      ),
                      const SizedBox(height: 8),
                      const Text(
                        'Set or change your password. OAuth users (Google/Meta) can set a password here.',
                      ),
                      const SizedBox(height: 12),
                      TextFormField(
                        controller: _newPasswordController,
                        decoration: const InputDecoration(
                          labelText: 'New password',
                        ),
                        obscureText: true,
                        validator: (v) {
                          if (v == null || v.isEmpty) {
                            return null; // allow empty to skip
                          }
                          if ((v).length < 8) {
                            return 'Password must be at least 8 characters';
                          }
                          return null;
                        },
                      ),
                      const SizedBox(height: 8),
                      TextFormField(
                        controller: _confirmPasswordController,
                        decoration: const InputDecoration(
                          labelText: 'Confirm password',
                        ),
                        obscureText: true,
                        validator: (v) {
                          final pw = _newPasswordController.text;
                          if (pw.isEmpty) {
                            return null;
                          }
                          if (v != pw) {
                            return 'Passwords do not match';
                          }
                          return null;
                        },
                      ),
                      const SizedBox(height: 12),
                      Row(
                        children: [
                          ElevatedButton(
                            onPressed: _changingPassword
                                ? null
                                : _onChangePassword,
                            child: Text(
                              _changingPassword
                                  ? 'Updating...'
                                  : 'Change password',
                            ),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ),
            ),

            const SizedBox(height: 12),

            // Offices Card
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Offices',
                      style: Theme.of(context).textTheme.titleMedium,
                    ),
                    const SizedBox(height: 12),
                    officesAsync.when(
                      data: (offices) {
                        return Column(
                          children: [
                            MultiSelectPicker<Office>(
                              label: 'Offices',
                              items: offices,
                              selectedIds: _selectedOfficeIds,
                              getId: (o) => o.id,
                              getLabel: (o) => o.name,
                              onChanged: (ids) =>
                                  setState(() => _selectedOfficeIds = ids),
                            ),
                            const SizedBox(height: 12),
                            Row(
                              children: [
                                ElevatedButton(
                                  onPressed: _savingOffices
                                      ? null
                                      : _onSaveOffices,
                                  child: Text(
                                    _savingOffices
                                        ? 'Saving...'
                                        : 'Save offices',
                                  ),
                                ),
                              ],
                            ),
                          ],
                        );
                      },
                      loading: () =>
                          const Center(child: CircularProgressIndicator()),
                      error: (e, _) => Text('Failed to load offices: $e'),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Future<void> _onSaveDetails() async {
    if (!_detailsKey.currentState!.validate()) return;
    final id = ref.read(currentUserIdProvider);
    if (id == null) return;
    setState(() => _savingDetails = true);
    try {
      await ref
          .read(profileControllerProvider)
          .updateFullName(
            userId: id,
            fullName: _fullNameController.text.trim(),
          );
      if (!mounted) return;
      ScaffoldMessenger.of(
        context,
      ).showSnackBar(const SnackBar(content: Text('Profile updated.')));
      // Refresh providers so other UI picks up the change immediately
      ref.invalidate(currentProfileProvider);
      ref.invalidate(profilesProvider);
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(
        context,
      ).showSnackBar(SnackBar(content: Text('Update failed: $e')));
    } finally {
      if (mounted) setState(() => _savingDetails = false);
    }
  }

  Future<void> _onChangePassword() async {
    if (!_passwordKey.currentState!.validate()) return;
    final pw = _newPasswordController.text;
    if (pw.isEmpty) {
      // nothing to do
      return;
    }
    setState(() => _changingPassword = true);
    try {
      await ref.read(profileControllerProvider).updatePassword(pw);
      _newPasswordController.clear();
      _confirmPasswordController.clear();
      if (!mounted) return;
      ScaffoldMessenger.of(
        context,
      ).showSnackBar(const SnackBar(content: Text('Password updated.')));
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(
        context,
      ).showSnackBar(SnackBar(content: Text('Password update failed: $e')));
    } finally {
      if (mounted) setState(() => _changingPassword = false);
    }
  }

  Future<void> _onSaveOffices() async {
    final id = ref.read(currentUserIdProvider);
    if (id == null) return;
    setState(() => _savingOffices = true);
    try {
      final assignments = ref.read(userOfficesProvider).valueOrNull ?? [];
      final assigned = assignments
          .where((a) => a.userId == id)
          .map((a) => a.officeId)
          .toSet();
      final selected = _selectedOfficeIds.toSet();

      final toAdd = selected.difference(assigned);
      final toRemove = assigned.difference(selected);

      final ctrl = ref.read(userOfficesControllerProvider);
      for (final officeId in toAdd) {
        await ctrl.assignUserOffice(userId: id, officeId: officeId);
      }
      for (final officeId in toRemove) {
        await ctrl.removeUserOffice(userId: id, officeId: officeId);
      }

      if (!mounted) return;
      ScaffoldMessenger.of(
        context,
      ).showSnackBar(const SnackBar(content: Text('Offices updated.')));
      ref.invalidate(userOfficesProvider);
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(
        context,
      ).showSnackBar(SnackBar(content: Text('Failed to save offices: $e')));
    } finally {
      if (mounted) setState(() => _savingOffices = false);
    }
  }
}
