import {
  ChangeDetectionStrategy,
  Component,
  computed,
  inject,
  input,
  signal,
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { CdkDrag, CdkDragDrop, CdkDropList } from '@angular/cdk/drag-drop';
import { SimpleCounter, SimpleCounterType } from '../simple-counter.model';
import { SimpleCounterService } from '../simple-counter.service';
import { DateService } from '../../../core/date/date.service';
import { T } from '../../../t.const';
import { TranslateModule } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatDialog } from '@angular/material/dialog';
import { DialogSimpleCounterEditComponent } from '../dialog-simple-counter-edit/dialog-simple-counter-edit.component';
import { DialogSimpleCounterEditSettingsComponent } from '../dialog-simple-counter-edit-settings/dialog-simple-counter-edit-settings.component';
import { DialogConfirmComponent } from '../../../ui/dialog-confirm/dialog-confirm.component';
import { EMPTY_SIMPLE_COUNTER } from '../simple-counter.const';
import { MatTooltipModule } from '@angular/material/tooltip';
import { moveItemInArray } from '../../../util/move-item-in-array';
import { dragDelayForTouch } from '../../../util/input-intent';
import { LocaleDatePipe } from 'src/app/ui/pipes/locale-date.pipe';
import { DateTimeFormatService } from 'src/app/core/date-time-format/date-time-format.service';

interface HabitDay {
  str: string;
  date: Date;
  dow: number;
}

@Component({
  selector: 'habit-tracker',
  standalone: true,
  imports: [
    CommonModule,
    TranslateModule,
    MatButtonModule,
    MatIconModule,
    MatTooltipModule,
    CdkDropList,
    CdkDrag,
    LocaleDatePipe,
  ],
  templateUrl: './habit-tracker.component.html',
  styleUrl: './habit-tracker.component.scss',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HabitTrackerComponent {
  simpleCounters = input.required<SimpleCounter[]>();
  disabledSimpleCounters = input<SimpleCounter[]>([]);

  private _simpleCounterService = inject(SimpleCounterService);
  private _dateTimeFormatService = inject(DateTimeFormatService);
  private _dateService = inject(DateService);
  private _matDialog = inject(MatDialog);

  // Exposed so templates can pass the reactive locale to the now-pure
  // `localeDate` pipe, preserving re-render on a locale change.
  readonly locale = this._dateTimeFormatService.currentLocale;

  showDisabled = signal(false);

  T = T;
  SimpleCounterType = SimpleCounterType;
  dragDelayForTouch = dragDelayForTouch;

  dayOffset = signal(0);

  days = computed(() => {
    const days: HabitDay[] = [];
    const today = new Date();
    const offset = this.dayOffset();
    for (let i = 6; i >= 0; i--) {
      const d = new Date();
      d.setDate(today.getDate() - i + offset);
      days.push({
        str: this._dateService.todayStr(d),
        date: d,
        dow: d.getDay(),
      });
    }
    return days;
  });

  prevWeek(): void {
    this.dayOffset.update((offset) => offset - 7);
  }

  nextWeek(): void {
    this.dayOffset.update((offset) => Math.min(0, offset + 7));
  }

  resetToToday(): void {
    this.dayOffset.set(0);
  }

  drop(event: CdkDragDrop<SimpleCounter[]>): void {
    if (event.previousIndex === event.currentIndex) {
      return;
    }
    const counters = this.simpleCounters();
    this._simpleCounterService.updateOrder(
      moveItemInArray(counters, event.previousIndex, event.currentIndex).map((c) => c.id),
    );
  }

  dateRangeLabel = computed(() => {
    const days = this.days();
    if (days.length === 0) return '';
    const first = days[0].date;
    const last = days[days.length - 1].date;

    const locale = this._dateTimeFormatService.currentLocale();
    const formatOptions: Intl.DateTimeFormatOptions = { month: 'short', day: 'numeric' };
    const firstStr = first.toLocaleDateString(locale, formatOptions);
    const lastStr = last.toLocaleDateString(locale, formatOptions);

    return `${firstStr} - ${lastStr}`;
  });

  private _longPressTimer?: number;
  private _isLongPress = false;
  private _pendingLongPressAction?: { counter: SimpleCounter; date: string };

  onCellClick(counter: SimpleCounter, date: string, dow: number): void {
    if (!this.isDayEnabled(counter, dow)) {
      return;
    }
    if (this._isLongPress) {
      this._isLongPress = false;
      return;
    }

    const currentValue = this.getVal(counter, date);

    if (
      counter.type === SimpleCounterType.ClickCounter ||
      counter.type === SimpleCounterType.RepeatedCountdownReminder
    ) {
      // Increment for ClickCounters on left click
      const newVal = currentValue + 1;
      this._simpleCounterService.setCounterForDate(counter.id, date, newVal);
    } else {
      // For StopWatch or others, open dialog on left click
      this.openEditDialog(counter, date);
    }
  }

  onCellContextMenu(
    event: MouseEvent,
    counter: SimpleCounter,
    date: string,
    dow: number,
  ): void {
    event.preventDefault();
    if (!this.isDayEnabled(counter, dow)) {
      return;
    }
    this.openEditDialog(counter, date);
  }

  onPressStart(counter: SimpleCounter, date: string, dow: number): void {
    if (!this.isDayEnabled(counter, dow)) {
      return;
    }
    this._isLongPress = false;
    this._pendingLongPressAction = undefined;
    this._longPressTimer = window.setTimeout(() => {
      this._isLongPress = true;
      this._pendingLongPressAction = { counter, date };
    }, 700); // 700ms for long press
  }

  onPressEnd(): void {
    if (this._longPressTimer) {
      window.clearTimeout(this._longPressTimer);
      this._longPressTimer = undefined;
    }

    // If long press was triggered, open dialog on release
    if (this._pendingLongPressAction) {
      const { counter, date } = this._pendingLongPressAction;
      this._pendingLongPressAction = undefined;
      this.openEditDialog(counter, date);
    }
  }

  openEditDialog(counter: SimpleCounter, date: string): void {
    const counterCopy = {
      ...counter,
      countOnDay: { ...counter.countOnDay },
    };

    this._matDialog.open(DialogSimpleCounterEditComponent, {
      data: { simpleCounter: counterCopy, selectedDate: date },
      restoreFocus: true,
    });
  }

  isDayEnabled(counter: SimpleCounter, dow: number): boolean {
    if (!counter.isTrackStreaks || counter.streakMode === 'weekly-frequency') {
      return true;
    }
    // Default to 'specific-days' logic
    if (!counter.streakWeekDays) {
      return true;
    }
    return !!counter.streakWeekDays[dow];
  }

  isSimpleCompletion(counter: SimpleCounter): boolean {
    // Simple completion: ClickCounter type with no specific goal or goal of 1
    return (
      counter.type === SimpleCounterType.ClickCounter &&
      (!counter.streakMinValue || counter.streakMinValue === 1)
    );
  }

  getVal(counter: SimpleCounter, day: string): number {
    return counter.countOnDay?.[day] ?? 0;
  }

  getDisplayValue(counter: SimpleCounter, day: string): string {
    const value = this.getVal(counter, day);
    if (value === 0) return '';

    // For simple completion, just show checkmark (handled in template)
    if (this.isSimpleCompletion(counter)) {
      return '';
    }

    // For StopWatch, show time
    if (counter.type === SimpleCounterType.StopWatch) {
      // Convert ms to minutes for display
      const minutes = Math.round(value / 60000);
      if (minutes < 60) {
        return `${minutes}m`;
      } else {
        const hours = Math.floor(minutes / 60);
        const mins = minutes % 60;
        return mins > 0 ? `${hours}h${mins}m` : `${hours}h`;
      }
    }

    // For ClickCounter with specific values, show the count
    return value.toString();
  }

  getProgress(counter: SimpleCounter, day: string): number {
    const value = this.getVal(counter, day);
    if (value === 0) return 0;

    const goal = counter.streakMinValue || 1;
    return Math.min(100, (value / goal) * 100);
  }

  addHabit(): void {
    const newHabit = {
      ...EMPTY_SIMPLE_COUNTER,
      isEnabled: true,
    };

    this._matDialog.open(DialogSimpleCounterEditSettingsComponent, {
      data: { simpleCounter: newHabit },
      restoreFocus: true,
      width: '600px',
    });
  }

  openEditSettings(counter: SimpleCounter): void {
    const counterCopy = {
      ...counter,
      countOnDay: { ...counter.countOnDay },
    };

    this._matDialog.open(DialogSimpleCounterEditSettingsComponent, {
      data: { simpleCounter: counterCopy },
      restoreFocus: true,
      width: '600px',
    });
  }

  enableHabit(id: string): void {
    this._simpleCounterService.updateSimpleCounter(id, { isEnabled: true });
  }

  deleteHabit(counter: SimpleCounter): void {
    this._matDialog
      .open(DialogConfirmComponent, {
        restoreFocus: true,
        data: {
          message: T.F.SIMPLE_COUNTER.D_CONFIRM_REMOVE.MSG,
          okTxt: T.F.SIMPLE_COUNTER.D_CONFIRM_REMOVE.OK,
        },
      })
      .afterClosed()
      .subscribe((confirmed: boolean) => {
        if (confirmed) {
          this._simpleCounterService.deleteSimpleCounter(counter.id);
        }
      });
  }
}
