import 'package:scheduler_core/scheduler_core.dart';

import '../controllers/scheduler_command_controller.dart';
import '../controllers/scheduler_read_controller.dart';

class DemoSchedulerComposition {
  DemoSchedulerComposition._({
    required this.store,
    required this.todayQuery,
    required this.managementUseCases,
    required this.commandUseCases,
    required this.now,
    required this.date,
  });

  final InMemoryApplicationUnitOfWork store;
  final GetTodayStateQuery todayQuery;
  final V1ApplicationManagementUseCases managementUseCases;
  final V1ApplicationCommandUseCases commandUseCases;
  final DateTime now;
  final CivilDate date;

  factory DemoSchedulerComposition.seeded({
    bool includeTodayItems = true,
    bool includeBacklogItems = true,
  }) {
    final now = DateTime.utc(2026, 6, 25, 9, 15);
    final date = CivilDate(2026, 6, 25);
    final createdAt = DateTime.utc(2026, 6, 20, 8);
    final project = ProjectProfile(id: 'home', name: 'Home', colorKey: 'home');
    final store = InMemoryApplicationUnitOfWork(
      initialProjects: [project],
      initialOwnerSettings: [
        OwnerSettings(
          ownerId: 'owner-1',
          timeZoneId: 'UTC',
          compactModeEnabled: true,
          backlogStalenessSettings: const BacklogStalenessSettings(
            greenMaxAge: Duration(days: 2),
            blueMaxAge: Duration(days: 6),
          ),
        ),
      ],
      initialTasks: [
        if (includeTodayItems) ...[
          _scheduledTask(
            id: 'plan-day',
            title: 'Plan the day',
            type: TaskType.flexible,
            start: DateTime.utc(2026, 6, 25, 9),
            end: DateTime.utc(2026, 6, 25, 9, 30),
            createdAt: createdAt,
          ),
          _scheduledTask(
            id: 'appointment',
            title: 'Appointment',
            type: TaskType.inflexible,
            start: DateTime.utc(2026, 6, 25, 10),
            end: DateTime.utc(2026, 6, 25, 10, 45),
            createdAt: createdAt,
          ),
          _scheduledTask(
            id: 'rest',
            title: 'Protected rest',
            type: TaskType.freeSlot,
            start: DateTime.utc(2026, 6, 25, 11),
            end: DateTime.utc(2026, 6, 25, 11, 30),
            createdAt: createdAt,
          ),
        ],
        if (includeBacklogItems) ...[
          _backlogTask(
            id: 'fresh',
            title: 'Send project update',
            createdAt: now.subtract(const Duration(days: 1)),
          ),
          _backlogTask(
            id: 'stale',
            title: 'Sort receipts',
            createdAt: now.subtract(const Duration(days: 9)),
          ),
        ],
      ],
    );

    return DemoSchedulerComposition._(
      store: store,
      todayQuery: GetTodayStateQuery(
        applicationStore: store,
        timeZoneResolver: const FixedOffsetTimeZoneResolver.utc(),
      ),
      managementUseCases: V1ApplicationManagementUseCases(
        applicationStore: store,
      ),
      commandUseCases: V1ApplicationCommandUseCases(
        applicationStore: store,
        timeZoneResolver: const FixedOffsetTimeZoneResolver.utc(),
      ),
      now: now,
      date: date,
    );
  }

  UiReadController<TodayState> createTodayController() {
    return ApplicationReadController<TodayState>(
      read: () {
        return todayQuery.execute(
          GetTodayStateRequest(
            context: context('ui-read-today'),
            date: date,
            includeNextFlexibleItem: true,
          ),
        );
      },
      isEmpty: (state) {
        return state.timelineItems.isEmpty && state.pendingNotices.isEmpty;
      },
    );
  }

  UiReadController<BacklogQueryResult> createBacklogController() {
    return ApplicationReadController<BacklogQueryResult>(
      read: () {
        return managementUseCases.getBacklog(
          GetBacklogRequest(
            context: context('ui-read-backlog'),
            sortKey: BacklogSortKey.age,
          ),
        );
      },
      isEmpty: (state) => state.items.isEmpty,
    );
  }

  SchedulerCommandController createCommandController({
    required ReadRefresh refreshReads,
  }) {
    return SchedulerCommandController(
      commands: commandUseCases,
      contextFor: context,
      localDate: date,
      refreshReads: refreshReads,
    );
  }

  ApplicationOperationContext context(String operationId) {
    return ApplicationOperationContext.start(
      operationId: operationId,
      ownerTimeZone: OwnerTimeZoneContext(
        ownerId: 'owner-1',
        timeZoneId: 'UTC',
      ),
      clock: FixedClock(now),
      idGenerator: SequentialIdGenerator(prefix: operationId),
    );
  }
}

Task _scheduledTask({
  required String id,
  required String title,
  required TaskType type,
  required DateTime start,
  required DateTime end,
  required DateTime createdAt,
}) {
  return Task(
    id: id,
    title: title,
    projectId: 'home',
    type: type,
    status: TaskStatus.planned,
    priority: PriorityLevel.medium,
    reward: RewardLevel.medium,
    difficulty: DifficultyLevel.easy,
    durationMinutes: end.difference(start).inMinutes,
    scheduledStart: start,
    scheduledEnd: end,
    createdAt: createdAt,
    updatedAt: createdAt,
  );
}

Task _backlogTask({
  required String id,
  required String title,
  required DateTime createdAt,
}) {
  return Task.quickCapture(
    id: id,
    title: title,
    projectId: 'home',
    createdAt: createdAt,
    updatedAt: createdAt,
  );
}
