import { LitElement, css, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import type { CalendarEventData } from './CalendarEvent';

@customElement('arx-calendar-month-view')
export class CalendarMonthView extends LitElement {
  @property({ type: Date })
  currentDate = new Date();

  @property({ type: Date })
  selectedDate: Date | null = null;

  @property({ type: Array })
  events: CalendarEventData[] = [];

  @property({ type: String })
  locale = 'en-US';

  static override styles = css`
    .calendar-grid {
      display: grid;
      grid-template-columns: repeat(7, 1fr);
      gap: 0.5rem;
      background: var(--color-base-100);
      padding: 1rem;
      border-radius: var(--radius-selector);
      box-shadow: var(--shadow-sm);
    }

    .calendar-day-header {
      text-align: center;
      padding: 0.5rem;
      font-weight: 500;
      color: var(--color-base-content);
      opacity: 0.7;
    }

    .calendar-day {
      aspect-ratio: 1;
      display: flex;
      flex-direction: column;
      align-items: stretch;
      justify-content: center;
      min-height: 100px;
      position: relative;
      overflow: hidden;
      border: 1px solid var(--color-base-300);
      border-radius: var(--radius-selector);
      cursor: pointer;
      transition: all 0.2s ease;
      background: var(--color-base-200);
      color: var(--color-base-content);
    }

    .calendar-day-number {
      text-align: center;
      padding: 0.25rem;
      font-weight: 500;
    }

    .calendar-day:hover {
      background: var(--color-base-300);
      transform: translateY(-2px);
    }

    .calendar-day.selected {
      background: var(--color-primary);
      color: var(--color-primary-content);
      border-color: var(--color-primary);
    }

    .calendar-day.today {
      border: 2px solid var(--color-primary);
      font-weight: 600;
    }

    .calendar-day.other-month {
      opacity: 0.5;
      background: var(--color-base-100);
    }

    .calendar-day-events {
      flex: 1;
      overflow-y: auto;
      max-height: 100px;
      width: 100%;
    }
  `;

  private getDaysInMonth(date: Date): number {
    return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
  }

  private getFirstDayOfMonth(date: Date): number {
    return new Date(date.getFullYear(), date.getMonth(), 1).getDay();
  }

  private getCalendarDays(): Date[] {
    const days: Date[] = [];
    const firstDay = this.getFirstDayOfMonth(this.currentDate);
    const daysInMonth = this.getDaysInMonth(this.currentDate);
    const daysInPrevMonth = this.getDaysInMonth(
      new Date(this.currentDate.getFullYear(), this.currentDate.getMonth() - 1),
    );

    for (let i = firstDay - 1; i >= 0; i--) {
      days.push(new Date(this.currentDate.getFullYear(), this.currentDate.getMonth() - 1, daysInPrevMonth - i));
    }

    for (let i = 1; i <= daysInMonth; i++) {
      days.push(new Date(this.currentDate.getFullYear(), this.currentDate.getMonth(), i));
    }

    const remainingDays = 42 - days.length; // 6 rows * 7 days
    for (let i = 1; i <= remainingDays; i++) {
      days.push(new Date(this.currentDate.getFullYear(), this.currentDate.getMonth() + 1, i));
    }

    return days;
  }

  private isToday(date: Date): boolean {
    const today = new Date();
    return (
      date.getDate() === today.getDate() &&
      date.getMonth() === today.getMonth() &&
      date.getFullYear() === today.getFullYear()
    );
  }

  private isSelected(date: Date): boolean {
    if (!this.selectedDate) return false;
    return (
      date.getDate() === this.selectedDate.getDate() &&
      date.getMonth() === this.selectedDate.getMonth() &&
      date.getFullYear() === this.selectedDate.getFullYear()
    );
  }

  private isOtherMonth(date: Date): boolean {
    return date.getMonth() !== this.currentDate.getMonth();
  }

  private getEventsForDate(date: Date): CalendarEventData[] {
    return this.events.filter((event) => {
      const eventStart = new Date(event.start);
      if (
        eventStart.getDate() === date.getDate() &&
        eventStart.getMonth() === date.getMonth() &&
        eventStart.getFullYear() === date.getFullYear()
      ) {
        return true;
      }

      if (!event.end) return false;

      const eventEnd = new Date(event.end);

      return (
        eventEnd.getDate() === date.getDate() &&
        eventEnd.getMonth() === date.getMonth() &&
        eventEnd.getFullYear() === date.getFullYear()
      );
    });
  }

  private handleDateClick(date: Date) {
    this.dispatchEvent(new CustomEvent('date-click', { detail: { date } }));
  }

  private handleEventClick(event: CalendarEventData) {
    this.dispatchEvent(new CustomEvent('event-click', { detail: { event } }));
  }

  override render() {
    const firstDay = new Date(2024, 0, 1);
    const dayNames = Array.from({ length: 7 }, (_, i) => {
      const date = new Date(firstDay);
      date.setDate(firstDay.getDate() + i);
      return date.toLocaleDateString(this.locale, { weekday: 'short' });
    });

    return html`
      <div class="calendar-grid">
        ${dayNames.map((day) => html`<div class="calendar-day-header">${day}</div>`)}
        ${this.getCalendarDays().map(
          (date) => html`
            <div
              class="calendar-day ${this.isToday(date) ? 'today' : ''} ${
                this.isSelected(date) ? 'selected' : ''
              } ${this.isOtherMonth(date) ? 'other-month' : ''}"
              @click=${() => this.handleDateClick(date)}
            >
              <div class="calendar-day-number">${date.getDate()}</div>
              <div class="calendar-day-events">
                ${this.getEventsForDate(date).map(
                  (event) => html`
                    <arx-calendar-event
                      .event=${event}
                      .locale=${this.locale}
                      @event-click=${(e: CustomEvent) => this.handleEventClick(e.detail.event)}
                    ></arx-calendar-event>
                  `,
                )}
              </div>
            </div>
          `,
        )}
      </div>
    `;
  }
}
