import 'package:flutter/material.dart';
import 'package:habo/constants.dart';
import 'package:habo/habits/habit.dart';
import 'package:habo/model/habit_data.dart';
import 'package:habo/model/habo_model.dart';
import 'package:habo/repositories/habit_repository.dart';

class SqliteHabitRepository implements HabitRepository {
  final HaboModel _model;

  SqliteHabitRepository(this._model);

  @override
  Future<List<Habit>> getAllHabits() async {
    final maps = await _model.getAllHabits();
    return maps.map((map) {
      final data = _mapToHabitData(map);
      return Habit(habitData: data);
    }).toList();
  }

  @override
  Future<int> createHabit(Habit habit) async {
    return _model.insertHabit(habit.habitData);
  }

  @override
  Future<void> updateHabit(Habit habit) async {
    await _model.updateHabit(habit.habitData);
  }

  @override
  Future<void> deleteHabit(int id) async {
    await _model.deleteHabit(id);
  }

  @override
  Future<Habit?> findHabitById(int id) async {
    final map = await _model.getHabitById(id);
    if (map == null) return null;
    final data = _mapToHabitData(map);
    return Habit(habitData: data);
  }

  @override
  Future<void> updateHabitsOrder(List<Habit> habits) async {
    await _model.updateHabitsOrder(habits);
  }

  @override
  Future<void> deleteAllHabits() async {
    await _model.deleteAllHabits();
  }

  @override
  Future<void> insertHabits(List<Habit> habits) async {
    for (final habit in habits) {
      await _model.insertHabit(habit.habitData);
    }
  }

  HabitData _mapToHabitData(Map<String, dynamic> map) {
    return HabitData(
      id: map['id'] as int?,
      position: map['position'] as int? ?? 0,
      title: map['title'] as String? ?? '',
      twoDayRule: (map['twoDayRule'] as int? ?? 0) == 1,
      cue: map['cue'] as String? ?? '',
      routine: map['routine'] as String? ?? '',
      reward: map['reward'] as String? ?? '',
      showReward: (map['showReward'] as int? ?? 0) == 1,
      advanced: (map['advanced'] as int? ?? 0) == 1,
      notification: (map['notification'] as int? ?? 0) == 1,
      notTime: _parseTimeOfDay(map['notTime'] as String? ?? ''),
      sanction: map['sanction'] as String? ?? '',
      showSanction: (map['showSanction'] as int? ?? 0) == 1,
      accountant: map['accountant'] as String? ?? '',
      habitType: _indexToHabitType(map['habitType'] as int? ?? 0),
      targetValue: (map['targetValue'] as num?)?.toDouble() ?? 100.0,
      partialValue: (map['partialValue'] as num?)?.toDouble() ?? 10.0,
      unit: map['unit'] as String? ?? '',
      archived: (map['archived'] as int? ?? 0) == 1,
    );
  }

  HabitType _indexToHabitType(int index) {
    if (index >= 0 && index < HabitType.values.length) {
      return HabitType.values[index];
    }
    return HabitType.boolean;
  }

  TimeOfDay _parseTimeOfDay(String timeStr) {
    if (timeStr.isEmpty) return const TimeOfDay(hour: 20, minute: 0);
    try {
      final parts = timeStr.split(':');
      return TimeOfDay(
        hour: int.parse(parts[0]),
        minute: int.parse(parts[1]),
      );
    } catch (_) {
      return const TimeOfDay(hour: 20, minute: 0);
    }
  }
}
