import 'package:firebase_auth/firebase_auth.dart' as firebase;
import 'package:firebase_data_connect/firebase_data_connect.dart' as fdc;
import 'package:intl/intl.dart';
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
import 'package:krow_domain/krow_domain.dart';
// ignore: implementation_imports
import 'package:krow_domain/src/adapters/financial/time_card_adapter.dart';
import '../../domain/repositories/time_card_repository.dart';

/// Implementation of [TimeCardRepository] using Firebase Data Connect.
class TimeCardRepositoryImpl implements TimeCardRepository {
  final dc.ExampleConnector _dataConnect;
  final firebase.FirebaseAuth _firebaseAuth;

  /// Creates a [TimeCardRepositoryImpl].
  TimeCardRepositoryImpl({
    required dc.ExampleConnector dataConnect,
    required firebase.FirebaseAuth firebaseAuth,
  })  : _dataConnect = dataConnect,
        _firebaseAuth = firebaseAuth;

  Future<String> _getStaffId() async {
    final firebase.User? user = _firebaseAuth.currentUser;
    if (user == null) throw Exception('User not authenticated');

    final fdc.QueryResult<dc.GetStaffByUserIdData, dc.GetStaffByUserIdVariables> result =
        await _dataConnect.getStaffByUserId(userId: user.uid).execute();
    if (result.data.staffs.isEmpty) {
      throw Exception('Staff profile not found');
    }
    return result.data.staffs.first.id;
  }

  @override
  Future<List<TimeCard>> getTimeCards(DateTime month) async {
    final String staffId = await _getStaffId();
    // Fetch applications. Limit can be adjusted, assuming 100 is safe for now.
    final fdc.QueryResult<dc.GetApplicationsByStaffIdData, dc.GetApplicationsByStaffIdVariables> result =
        await _dataConnect.getApplicationsByStaffId(staffId: staffId).limit(100).execute();

    return result.data.applications
        .where((dc.GetApplicationsByStaffIdApplications app) {
          final DateTime? shiftDate = app.shift.date?.toDateTime();
          if (shiftDate == null) return false;
          return shiftDate.year == month.year && shiftDate.month == month.month;
        })
        .map((dc.GetApplicationsByStaffIdApplications app) {
          final DateTime shiftDate = app.shift.date!.toDateTime();
          final String startTime = _formatTime(app.checkInTime) ?? _formatTime(app.shift.startTime) ?? '';
          final String endTime = _formatTime(app.checkOutTime) ?? _formatTime(app.shift.endTime) ?? '';

          // Prefer shiftRole values for pay/hours
          final double hours = app.shiftRole.hours ?? 0.0;
          final double rate = app.shiftRole.role.costPerHour;
          final double pay = app.shiftRole.totalValue ?? 0.0;

          return TimeCardAdapter.fromPrimitives(
            id: app.id,
            shiftTitle: app.shift.title,
            clientName: app.shift.order.business.businessName,
            date: shiftDate,
            startTime: startTime,
            endTime: endTime,
            totalHours: hours,
            hourlyRate: rate,
            totalPay: pay,
            status: app.status.stringValue,
            location: app.shift.location,
          );
        })
        .toList();
  }

  String? _formatTime(fdc.Timestamp? timestamp) {
    if (timestamp == null) return null;
    return DateFormat('HH:mm').format(timestamp.toDateTime());
  }
}
