import 'dart:math';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'overtime_model.dart';
import 'overtime_api.dart';

class OvertimeCreateState {
  final OvertimeModel overtime;
  final bool isSubmitting;
  const OvertimeCreateState({required this.overtime, this.isSubmitting = false});
  OvertimeCreateState copyWith({OvertimeModel? overtime, bool? isSubmitting}) =>
      OvertimeCreateState(
        overtime: overtime ?? this.overtime,
        isSubmitting: isSubmitting ?? this.isSubmitting,
      );
}

class OvertimeCreateController extends StateNotifier<OvertimeCreateState> {
  final OvertimeApi _api;
  OvertimeCreateController(this._api)
    : super(
        OvertimeCreateState(
          overtime: OvertimeModel(
            id: '',
            applicationNo: '',
            applicantId: '',
            applicantName: '',
            deptId: '',
            deptName: '',
            otType: 'workday',
            compensationType: 'comp_leave',
            startTime: DateTime.now(),
            endTime: DateTime.now().add(const Duration(hours: 3)),
            netOtHours: 0.0,
            reason: '',
            createTime: DateTime.now(),
            updateTime: DateTime.now(),
          ),
        ),
      );

  void updateType(String t) =>
      state = state.copyWith(overtime: state.overtime.copyWith(otType: t));

  void updateCompensation(String c) {
    final newRatio = c == 'mixed'
        ? (state.overtime.compLeaveRatio ?? 0.5)
        : null;
    state = state.copyWith(
      overtime: state.overtime.copyWith(
        compensationType: c,
        compLeaveRatio: newRatio,
      ),
    );
  }

  void updateMixRatio(double v) {
    final ratio = (v / 10).round() * 10 / 100.0;
    state = state.copyWith(
      overtime: state.overtime.copyWith(compLeaveRatio: ratio),
    );
  }

  void updateStartTime(DateTime t) {
    state = state.copyWith(overtime: state.overtime.copyWith(startTime: t));
    _recalc();
  }

  void updateEndTime(DateTime t) {
    state = state.copyWith(overtime: state.overtime.copyWith(endTime: t));
    _recalc();
  }

  void updateReason(String r) =>
      state = state.copyWith(overtime: state.overtime.copyWith(reason: r));

  void _recalc() {
    final net = _calculateNetHours(
      state.overtime.startTime,
      state.overtime.endTime,
    );
    state = state.copyWith(overtime: state.overtime.copyWith(netOtHours: net));
  }

  /// 净工时 = (结束-开始) - 午餐(12:00-13:00) - 晚餐(18:00-18:30)
  double _calculateNetHours(DateTime start, DateTime end) {
    if (!end.isAfter(start)) return 0;
    final totalMinutes = end.difference(start).inMinutes;
    int deduction = 0;

    // 午餐盲区: 12:00-13:00
    final lunchS = DateTime(start.year, start.month, start.day, 12, 0);
    final lunchE = DateTime(start.year, start.month, start.day, 13, 0);
    deduction += _overlapMinutes(start, end, lunchS, lunchE);

    // 晚餐盲区: 18:00-18:30
    final dinnerS = DateTime(start.year, start.month, start.day, 18, 0);
    final dinnerE = DateTime(start.year, start.month, start.day, 18, 30);
    deduction += _overlapMinutes(start, end, dinnerS, dinnerE);

    return max(0, totalMinutes - deduction) / 60.0;
  }

  int _overlapMinutes(DateTime aS, DateTime aE, DateTime bS, DateTime bE) {
    final s = aS.isAfter(bS) ? aS : bS;
    final e = aE.isBefore(bE) ? aE : bE;
    if (!e.isAfter(s)) return 0;
    return e.difference(s).inMinutes;
  }

  bool validate() {
    final o = state.overtime;
    if (o.reason.trim().isEmpty) return false;
    if (!o.endTime.isAfter(o.startTime)) return false;
    if (o.netOtHours <= 0) return false;
    return true;
  }

  Future<bool> submit() async {
    if (!validate()) return false;
    state = state.copyWith(isSubmitting: true);
    try {
      await _api.submit(state.overtime.copyWith(status: 'pending'));
      return true;
    } catch (_) {
      return false;
    } finally {
      state = state.copyWith(isSubmitting: false);
    }
  }

  Future<bool> saveDraft() async {
    state = state.copyWith(isSubmitting: true);
    try {
      await _api.saveDraft(state.overtime);
      return true;
    } catch (_) {
      return false;
    } finally {
      state = state.copyWith(isSubmitting: false);
    }
  }
}

final overtimeCreateProvider = StateNotifierProvider.autoDispose
    .family<OvertimeCreateController, OvertimeCreateState, String?>((
      ref,
      editId,
    ) {
      return OvertimeCreateController(ref.read(overtimeApiProvider));
    });
