import 'package:hive_flutter/hive_flutter.dart';

/// Hive type adapter IDs and box names.
class HiveBoxes {
  HiveBoxes._();
  static const String settings = 'app_settings';
  static const String prayerSchedule = 'prayer_schedule';
}

/// AppSettings stored in Hive.
@HiveType(typeId: 0)
class AppSettings extends HiveObject {
  @HiveField(0)
  String masjidName;

  @HiveField(1)
  String masjidAddress;

  @HiveField(2)
  String cityIdApi; // myQuran city hash ID

  @HiveField(3)
  String cityDisplayName;

  @HiveField(4)
  bool showImsak;

  @HiveField(5)
  bool showTerbit;

  // Iqomah durations in minutes
  @HiveField(6)
  int iqomahSubuh;

  @HiveField(7)
  int iqomahDzuhur;

  @HiveField(8)
  int iqomahAshar;

  @HiveField(9)
  int iqomahMaghrib;

  @HiveField(10)
  int iqomahIsya;

  // Pre-Adzan lead time (minutes before adzan to lock main screen)
  @HiveField(11)
  int preAdzanLead;

  // Blank screen durations
  @HiveField(12)
  int blankScreenNormal;  // minutes

  @HiveField(13)
  int blankScreenJumat;   // minutes

  // Running text items
  @HiveField(14)
  List<String> runningTexts;

  // Friday officers
  @HiveField(15)
  String khatibName;

  @HiveField(16)
  String imamName;

  // Rotation settings
  @HiveField(17)
  int mainScreenDurationSec;

  @HiveField(18)
  int slideDurationSec;

  // Last sync timestamp
  @HiveField(19)
  String? lastSyncDate;

  // Last automatic sync attempt timestamp (ISO8601).
  @HiveField(32)
  String? lastAutoSyncAttemptDate;

  // Slideshow image paths (local)
  @HiveField(20)
  List<String> slideshowImages;

  // Text scaling (0=Small, 1=Medium, 2=Large)
  @HiveField(21)
  int textScaleIndex;

  // Unsplash Background configs
  @HiveField(22)
  bool useUnsplashBackground;

  @HiveField(23)
  String unsplashKeyword;

  @HiveField(24)
  int unsplashRotationHours;

  // Branded background image (local file path set by admin)
  @HiveField(25)
  String? brandedBgImage;

  // Per-item duration for running texts (seconds each)
  @HiveField(26)
  List<int> runningTextDurations;

  // Running text animation type: 'marquee' or 'fade'
  @HiveField(27)
  String marqueeAnimType;

  // Granular text group scales (independent of textScaleIndex)
  // Group: Prayer card label (e.g. "SUBUH", "DZUHUR")
  @HiveField(28)
  double scaleCardLabel;

  // Group: Prayer card body (time + iqomah text)
  @HiveField(29)
  double scaleCardBody;

  // Group: Running text ticker at bottom
  @HiveField(30)
  double scaleRunningText;

  // Manual day adjustment applied to displayed Hijri date.
  @HiveField(31)
  int hijriOffsetDays;

  AppSettings({
    this.masjidName = 'Masjid Al-Ikhlas',
    this.masjidAddress = 'Jl. Kebaikan No. 1',
    this.cityIdApi = '1218', // Default: Yogyakarta
    this.cityDisplayName = 'Kota Yogyakarta',
    this.showImsak = true,
    this.showTerbit = true,
    this.iqomahSubuh = 15,
    this.iqomahDzuhur = 10,
    this.iqomahAshar = 10,
    this.iqomahMaghrib = 7,
    this.iqomahIsya = 10,
    this.preAdzanLead = 10,
    this.blankScreenNormal = 15,
    this.blankScreenJumat = 45,
    this.runningTexts = const [
      'Mohon luruskan dan rapatkan shaf',
      'Kajian rutin setiap Ahad pagi',
    ],
    this.khatibName = 'Ust. Fulan, S.Ag',
    this.imamName = 'Ust. Alan, Lc',
    this.mainScreenDurationSec = 15,
    this.slideDurationSec = 10,
    this.lastSyncDate,
    this.lastAutoSyncAttemptDate,
    this.slideshowImages = const [],
    this.textScaleIndex = 1,
    this.useUnsplashBackground = false,
    this.unsplashKeyword = 'mosque',
    this.unsplashRotationHours = 6,
    this.brandedBgImage,
    this.runningTextDurations = const [],
    this.marqueeAnimType = 'marquee',
    this.scaleCardLabel = 1.0,
    this.scaleCardBody = 1.0,
    this.scaleRunningText = 1.0,
    this.hijriOffsetDays = 0,
  });

  AppSettings copyWith({
    String? masjidName,
    String? masjidAddress,
    String? cityIdApi,
    String? cityDisplayName,
    bool? showImsak,
    bool? showTerbit,
    int? iqomahSubuh,
    int? iqomahDzuhur,
    int? iqomahAshar,
    int? iqomahMaghrib,
    int? iqomahIsya,
    int? preAdzanLead,
    int? blankScreenNormal,
    int? blankScreenJumat,
    List<String>? runningTexts,
    String? khatibName,
    String? imamName,
    int? mainScreenDurationSec,
    int? slideDurationSec,
    String? lastSyncDate,
    String? lastAutoSyncAttemptDate,
    List<String>? slideshowImages,
    int? textScaleIndex,
    bool? useUnsplashBackground,
    String? unsplashKeyword,
    int? unsplashRotationHours,
    String? brandedBgImage,
    List<int>? runningTextDurations,
    String? marqueeAnimType,
    double? scaleCardLabel,
    double? scaleCardBody,
    double? scaleRunningText,
    int? hijriOffsetDays,
  }) {
    return AppSettings(
      masjidName: masjidName ?? this.masjidName,
      masjidAddress: masjidAddress ?? this.masjidAddress,
      cityIdApi: cityIdApi ?? this.cityIdApi,
      cityDisplayName: cityDisplayName ?? this.cityDisplayName,
      showImsak: showImsak ?? this.showImsak,
      showTerbit: showTerbit ?? this.showTerbit,
      iqomahSubuh: iqomahSubuh ?? this.iqomahSubuh,
      iqomahDzuhur: iqomahDzuhur ?? this.iqomahDzuhur,
      iqomahAshar: iqomahAshar ?? this.iqomahAshar,
      iqomahMaghrib: iqomahMaghrib ?? this.iqomahMaghrib,
      iqomahIsya: iqomahIsya ?? this.iqomahIsya,
      preAdzanLead: preAdzanLead ?? this.preAdzanLead,
      blankScreenNormal: blankScreenNormal ?? this.blankScreenNormal,
      blankScreenJumat: blankScreenJumat ?? this.blankScreenJumat,
      runningTexts: runningTexts ?? this.runningTexts,
      khatibName: khatibName ?? this.khatibName,
      imamName: imamName ?? this.imamName,
      mainScreenDurationSec: mainScreenDurationSec ?? this.mainScreenDurationSec,
      slideDurationSec: slideDurationSec ?? this.slideDurationSec,
      lastSyncDate: lastSyncDate ?? this.lastSyncDate,
      lastAutoSyncAttemptDate:
          lastAutoSyncAttemptDate ?? this.lastAutoSyncAttemptDate,
      slideshowImages: slideshowImages ?? this.slideshowImages,
      textScaleIndex: textScaleIndex ?? this.textScaleIndex,
      useUnsplashBackground: useUnsplashBackground ?? this.useUnsplashBackground,
      unsplashKeyword: unsplashKeyword ?? this.unsplashKeyword,
      unsplashRotationHours: unsplashRotationHours ?? this.unsplashRotationHours,
      brandedBgImage: brandedBgImage ?? this.brandedBgImage,
      runningTextDurations: runningTextDurations ?? this.runningTextDurations,
      marqueeAnimType: marqueeAnimType ?? this.marqueeAnimType,
      scaleCardLabel: scaleCardLabel ?? this.scaleCardLabel,
      scaleCardBody: scaleCardBody ?? this.scaleCardBody,
      scaleRunningText: scaleRunningText ?? this.scaleRunningText,
      hijriOffsetDays: hijriOffsetDays ?? this.hijriOffsetDays,
    );
  }
}

/// Adapter for AppSettings — hand-written to avoid code generation.
class AppSettingsAdapter extends TypeAdapter<AppSettings> {
  @override
  final int typeId = 0;

  @override
  AppSettings read(BinaryReader reader) {
    final numOfFields = reader.readByte();
    final fields = <int, dynamic>{};
    for (int i = 0; i < numOfFields; i++) {
      fields[reader.readByte()] = reader.read();
    }
    return AppSettings(
      masjidName: fields[0] as String? ?? 'Masjid Al-Ikhlas',
      masjidAddress: fields[1] as String? ?? 'Jl. Kebaikan No. 1',
      cityIdApi: fields[2] as String? ?? '1218',
      cityDisplayName: fields[3] as String? ?? 'Kota Yogyakarta',
      showImsak: fields[4] as bool? ?? true,
      showTerbit: fields[5] as bool? ?? true,
      iqomahSubuh: fields[6] as int? ?? 15,
      iqomahDzuhur: fields[7] as int? ?? 10,
      iqomahAshar: fields[8] as int? ?? 10,
      iqomahMaghrib: fields[9] as int? ?? 7,
      iqomahIsya: fields[10] as int? ?? 10,
      preAdzanLead: fields[11] as int? ?? 10,
      blankScreenNormal: fields[12] as int? ?? 15,
      blankScreenJumat: fields[13] as int? ?? 45,
      runningTexts: (fields[14] as List?)?.cast<String>() ?? const [],
      khatibName: fields[15] as String? ?? '',
      imamName: fields[16] as String? ?? '',
      mainScreenDurationSec: fields[17] as int? ?? 15,
      slideDurationSec: fields[18] as int? ?? 10,
      lastSyncDate: fields[19] as String?,
      lastAutoSyncAttemptDate: fields[32] as String?,
      slideshowImages: (fields[20] as List?)?.cast<String>() ?? const [],
      textScaleIndex: fields[21] as int? ?? 1,
      useUnsplashBackground: fields[22] as bool? ?? false,
      unsplashKeyword: fields[23] as String? ?? 'mosque',
      unsplashRotationHours: fields[24] as int? ?? 6,
      brandedBgImage: fields[25] as String?,
      runningTextDurations: (fields[26] as List?)?.cast<int>() ?? const [],
      marqueeAnimType: fields[27] as String? ?? 'marquee',
      scaleCardLabel: (fields[28] as num?)?.toDouble() ?? 1.0,
      scaleCardBody: (fields[29] as num?)?.toDouble() ?? 1.0,
      scaleRunningText: (fields[30] as num?)?.toDouble() ?? 1.0,
      hijriOffsetDays: fields[31] as int? ?? 0,
    );
  }

  @override
  void write(BinaryWriter writer, AppSettings obj) {
    writer
      ..writeByte(33)
      ..writeByte(0)..write(obj.masjidName)
      ..writeByte(1)..write(obj.masjidAddress)
      ..writeByte(2)..write(obj.cityIdApi)
      ..writeByte(3)..write(obj.cityDisplayName)
      ..writeByte(4)..write(obj.showImsak)
      ..writeByte(5)..write(obj.showTerbit)
      ..writeByte(6)..write(obj.iqomahSubuh)
      ..writeByte(7)..write(obj.iqomahDzuhur)
      ..writeByte(8)..write(obj.iqomahAshar)
      ..writeByte(9)..write(obj.iqomahMaghrib)
      ..writeByte(10)..write(obj.iqomahIsya)
      ..writeByte(11)..write(obj.preAdzanLead)
      ..writeByte(12)..write(obj.blankScreenNormal)
      ..writeByte(13)..write(obj.blankScreenJumat)
      ..writeByte(14)..write(obj.runningTexts)
      ..writeByte(15)..write(obj.khatibName)
      ..writeByte(16)..write(obj.imamName)
      ..writeByte(17)..write(obj.mainScreenDurationSec)
      ..writeByte(18)..write(obj.slideDurationSec)
      ..writeByte(19)..write(obj.lastSyncDate)
      ..writeByte(32)..write(obj.lastAutoSyncAttemptDate)
      ..writeByte(20)..write(obj.slideshowImages)
      ..writeByte(21)..write(obj.textScaleIndex)
      ..writeByte(22)..write(obj.useUnsplashBackground)
      ..writeByte(23)..write(obj.unsplashKeyword)
      ..writeByte(24)..write(obj.unsplashRotationHours)
      ..writeByte(25)..write(obj.brandedBgImage)
      ..writeByte(26)..write(obj.runningTextDurations)
      ..writeByte(27)..write(obj.marqueeAnimType)
      ..writeByte(28)..write(obj.scaleCardLabel)
      ..writeByte(29)..write(obj.scaleCardBody)
      ..writeByte(30)..write(obj.scaleRunningText)
      ..writeByte(31)..write(obj.hijriOffsetDays);
  }
}

/// Daily prayer schedule row cached from the MyQuran API.
@HiveType(typeId: 1)
class DailyPrayerSchedule extends HiveObject {
  @HiveField(0)
  String date; // yyyy-MM-dd

  @HiveField(1)
  String imsak;

  @HiveField(2)
  String subuh;

  @HiveField(3)
  String terbit;

  @HiveField(4)
  String dhuha;

  @HiveField(5)
  String dzuhur;

  @HiveField(6)
  String ashar;

  @HiveField(7)
  String maghrib;

  @HiveField(8)
  String isya;

  DailyPrayerSchedule({
    required this.date,
    required this.imsak,
    required this.subuh,
    required this.terbit,
    required this.dhuha,
    required this.dzuhur,
    required this.ashar,
    required this.maghrib,
    required this.isya,
  });

  /// Parse time string "HH:mm" to a DateTime on the given date.
  DateTime timeToDateTime(String time, DateTime refDate) {
    final parts = time.split(':');
    return DateTime(
      refDate.year,
      refDate.month,
      refDate.day,
      int.parse(parts[0]),
      int.parse(parts[1]),
    );
  }

  /// Get all prayer times as DateTime map for a given reference date.
  Map<String, DateTime> toDateTimeMap(DateTime refDate) => {
        'imsak': timeToDateTime(imsak, refDate),
        'subuh': timeToDateTime(subuh, refDate),
        'terbit': timeToDateTime(terbit, refDate),
        'dhuha': timeToDateTime(dhuha, refDate),
        'dzuhur': timeToDateTime(dzuhur, refDate),
        'ashar': timeToDateTime(ashar, refDate),
        'maghrib': timeToDateTime(maghrib, refDate),
        'isya': timeToDateTime(isya, refDate),
      };
}

/// Adapter for DailyPrayerSchedule.
class DailyPrayerScheduleAdapter extends TypeAdapter<DailyPrayerSchedule> {
  @override
  final int typeId = 1;

  @override
  DailyPrayerSchedule read(BinaryReader reader) {
    final numOfFields = reader.readByte();
    final fields = <int, dynamic>{};
    for (int i = 0; i < numOfFields; i++) {
      fields[reader.readByte()] = reader.read();
    }
    return DailyPrayerSchedule(
      date: fields[0] as String? ?? '',
      imsak: fields[1] as String? ?? '00:00',
      subuh: fields[2] as String? ?? '00:00',
      terbit: fields[3] as String? ?? '00:00',
      dhuha: fields[4] as String? ?? '00:00',
      dzuhur: fields[5] as String? ?? '00:00',
      ashar: fields[6] as String? ?? '00:00',
      maghrib: fields[7] as String? ?? '00:00',
      isya: fields[8] as String? ?? '00:00',
    );
  }

  @override
  void write(BinaryWriter writer, DailyPrayerSchedule obj) {
    writer
      ..writeByte(9)
      ..writeByte(0)..write(obj.date)
      ..writeByte(1)..write(obj.imsak)
      ..writeByte(2)..write(obj.subuh)
      ..writeByte(3)..write(obj.terbit)
      ..writeByte(4)..write(obj.dhuha)
      ..writeByte(5)..write(obj.dzuhur)
      ..writeByte(6)..write(obj.ashar)
      ..writeByte(7)..write(obj.maghrib)
      ..writeByte(8)..write(obj.isya);
  }
}
