// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only

part of '../../../time_contracts.dart';

/// Resolver for zones whose offset is already known by the application boundary.
class FixedOffsetTimeZoneResolver implements TimeZoneResolver {
  /// Creates a `FixedOffsetTimeZoneResolver.utc` instance with the values required by its invariants.
  /// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
  const FixedOffsetTimeZoneResolver.utc() : offset = Duration.zero;

  /// Creates a `FixedOffsetTimeZoneResolver` instance with the values required by its invariants.
  /// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
  const FixedOffsetTimeZoneResolver({required this.offset});

  /// Stores the `offset` value for this object.
  /// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
  final Duration offset;

  /// Performs the `resolve` behavior for this scheduler component.
  /// The method provides a named entry point for this operation so callers do not need to know the lower-level state or persistence steps involved.
  @override
  ResolvedLocalDateTime resolve({
    required CivilDate date,
    required WallTime wallTime,
    required String timeZoneId,
    TimeZoneResolutionOptions options = const TimeZoneResolutionOptions(),
  }) {
    final trimmedZone = timeZoneId.trim();
    if (trimmedZone.isEmpty) {
      throw DomainValidationException(
        code: DomainValidationCode.blankTimeZoneId,
        invalidValue: timeZoneId,
        name: 'timeZoneId',
        message: 'Time-zone id is required.',
      );
    }
    final localAsUtc = DateTime.utc(
      date.year,
      date.month,
      date.day,
      wallTime.hour,
      wallTime.minute,
    );

    return ResolvedLocalDateTime(
      date: date,
      wallTime: wallTime,
      timeZoneId: trimmedZone,
      instant: localAsUtc.subtract(offset),
      resolution: LocalTimeResolution.exact,
      utcOffset: offset,
    );
  }
}
