import {
  DeesElement,
  type TemplateResult,
  property,
  customElement,
  html,
  css,
  cssManager,
  state,
} from '@design.estate/dees-element';

import * as domtools from '@design.estate/dees-domtools';
import { DeesContextmenu } from '../../dees-contextmenu/dees-contextmenu.js';
import '../../dees-icon/dees-icon.js';
import type { IActivityEntry, IActivityLogAPI } from '../../interfaces/appconfig.js';
import { demoFunc } from './dees-appui-activitylog.demo.js';
import { themeDefaultStyles } from '../../00theme.js';

@customElement('dees-appui-activitylog')
export class DeesAppuiActivitylog extends DeesElement implements IActivityLogAPI {
  // STATIC
  public static demo = demoFunc;

  // INSTANCE PROPERTIES
  @state()
  accessor entries: IActivityEntry[] = [];

  @state()
  accessor searchQuery: string = '';

  @state()
  accessor filterCriteria: { user?: string; type?: IActivityEntry['type'] } = {};

  // RxJS Subject for reactive updates
  public entries$ = new domtools.plugins.smartrx.rxjs.Subject<IActivityEntry[]>();

  // STYLES
  public static styles = [
    themeDefaultStyles,
    cssManager.defaultStyles,
    css`
      /* TODO: Migrate hardcoded values to --dees-* CSS variables */
      :host {
        color: ${cssManager.bdTheme('#09090b', '#fafafa')};
        position: relative;
        display: block;
        width: 100%;
        max-width: 320px;
        height: 100%;
        background: ${cssManager.bdTheme('#fafafa', '#0a0a0a')};
        font-family: 'Geist Mono', monospace;
        border-left: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
        cursor: default;
        box-shadow: ${cssManager.bdTheme(
          '-4px 0 12px rgba(0, 0, 0, 0.02)',
          '-4px 0 12px rgba(0, 0, 0, 0.2)'
        )};
      }
      .maincontainer {
        position: absolute;
        top: 0px;
        left: 0px;
        height: 100%;
        width: 100%;
      }

      .topbar {
        position: absolute;
        top: 0px;
        height: 48px;
        width: 100%;
        padding: 0px 16px;
        background: ${cssManager.bdTheme('#ffffff', '#09090b')};
        border-bottom: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
        display: flex;
        align-items: center;
        box-sizing: border-box;
      }

      .topbar .heading {
        font-weight: 600;
        font-size: 14px;
        font-family: 'Geist Sans', sans-serif;
        color: ${cssManager.bdTheme('#09090b', '#fafafa')};
      }

      .activityContainer {
        position: absolute;
        top: 48px;
        bottom: 48px;
        width: 100%;
        padding: 12px 0px;
        overflow-y: auto;
        scrollbar-width: thin;
        scrollbar-color: ${cssManager.bdTheme('#e5e7eb', '#27272a')} transparent;
      }

      .activityContainer::-webkit-scrollbar {
        width: 6px;
      }

      .activityContainer::-webkit-scrollbar-track {
        background: transparent;
      }

      .activityContainer::-webkit-scrollbar-thumb {
        background: ${cssManager.bdTheme('#e5e7eb', '#27272a')};
        border-radius: 3px;
      }

      .activityContainer::-webkit-scrollbar-thumb:hover {
        background: ${cssManager.bdTheme('#d4d4d8', '#3f3f46')};
      }

      .empty-state {
        font-size: 13px;
        text-align: center;
        padding: 32px 16px;
        color: ${cssManager.bdTheme('#71717a', '#71717a')};
        font-family: 'Geist Sans', sans-serif;
      }

      .streamingIndicator {
        font-size: 11px;
        text-align: center;
        padding: 16px;
        color: ${cssManager.bdTheme('#71717a', '#71717a')};
        font-family: 'Geist Sans', sans-serif;
        text-transform: uppercase;
        letter-spacing: 0.05em;
        font-weight: 500;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 8px;
      }

      .streamingIndicator::before {
        content: '';
        width: 6px;
        height: 6px;
        background: ${cssManager.bdTheme('#3b82f6', '#3b82f6')};
        border-radius: 50%;
        animation: pulse 2s ease-in-out infinite;
      }

      @keyframes pulse {
        0%, 100% { opacity: 0.4; transform: scale(0.8); }
        50% { opacity: 1; transform: scale(1.2); }
      }

      .date-separator {
        padding: 12px 16px 8px;
        font-size: 11px;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.05em;
        color: ${cssManager.bdTheme('#71717a', '#71717a')};
        background: ${cssManager.bdTheme('#f9fafb', '#09090b')};
        border-bottom: 1px solid ${cssManager.bdTheme('#f4f4f5', '#18181b')};
        position: sticky;
        top: 0;
        z-index: 1;
      }

      .activityentry {
        min-height: 36px;
        font-size: 13px;
        padding: 10px 16px;
        border-bottom: 1px solid ${cssManager.bdTheme('#f4f4f5', '#18181b')};
        transition: all 0.15s ease;
        display: flex;
        align-items: center;
        gap: 8px;
        line-height: 1.4;
        animation: fadeIn 0.3s ease-out;
      }

      @keyframes fadeIn {
        from {
          opacity: 0;
          transform: translateY(-4px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .activityentry:last-of-type {
        border-bottom: none;
      }

      .activityentry:hover {
        background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
      }

      .timestamp {
        color: ${cssManager.bdTheme('#71717a', '#71717a')};
        font-weight: 500;
        font-size: 12px;
        font-variant-numeric: tabular-nums;
        flex-shrink: 0;
        min-width: 45px;
      }

      .activity-icon {
        width: 28px;
        height: 28px;
        border-radius: 6px;
        background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
        display: flex;
        align-items: center;
        justify-content: center;
        flex-shrink: 0;
        font-size: 14px;
      }

      .activity-icon.login {
        background: ${cssManager.bdTheme('rgba(34, 197, 94, 0.1)', 'rgba(34, 197, 94, 0.1)')};
        color: ${cssManager.bdTheme('#16a34a', '#22c55e')};
      }

      .activity-icon.logout {
        background: ${cssManager.bdTheme('rgba(239, 68, 68, 0.1)', 'rgba(239, 68, 68, 0.1)')};
        color: ${cssManager.bdTheme('#dc2626', '#ef4444')};
      }

      .activity-icon.view {
        background: ${cssManager.bdTheme('rgba(59, 130, 246, 0.1)', 'rgba(59, 130, 246, 0.1)')};
        color: ${cssManager.bdTheme('#2563eb', '#3b82f6')};
      }

      .activity-icon.create {
        background: ${cssManager.bdTheme('rgba(168, 85, 247, 0.1)', 'rgba(168, 85, 247, 0.1)')};
        color: ${cssManager.bdTheme('#9333ea', '#a855f7')};
      }

      .activity-icon.update {
        background: ${cssManager.bdTheme('rgba(251, 146, 60, 0.1)', 'rgba(251, 146, 60, 0.1)')};
        color: ${cssManager.bdTheme('#ea580c', '#fb923c')};
      }

      .activity-icon.delete {
        background: ${cssManager.bdTheme('rgba(239, 68, 68, 0.1)', 'rgba(239, 68, 68, 0.1)')};
        color: ${cssManager.bdTheme('#dc2626', '#ef4444')};
      }

      .activity-icon.custom {
        background: ${cssManager.bdTheme('rgba(100, 116, 139, 0.1)', 'rgba(100, 116, 139, 0.1)')};
        color: ${cssManager.bdTheme('#475569', '#94a3b8')};
      }

      .activity-text {
        flex: 1;
        color: ${cssManager.bdTheme('#18181b', '#e4e4e7')};
      }

      .activity-user {
        font-weight: 600;
        color: ${cssManager.bdTheme('#09090b', '#fafafa')};
      }

      .searchbox {
        position: absolute;
        bottom: 0px;
        width: 100%;
        height: 48px;
        background: ${cssManager.bdTheme('#ffffff', '#09090b')};
        border-top: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
        padding: 8px;
      }

      .search-wrapper {
        position: relative;
        width: 100%;
        height: 32px;
      }

      .search-icon {
        position: absolute;
        left: 10px;
        top: 50%;
        transform: translateY(-50%);
        color: ${cssManager.bdTheme('#71717a', '#71717a')};
        font-size: 14px;
        pointer-events: none;
        transition: color 0.15s ease;
      }

      .searchbox input {
        color: ${cssManager.bdTheme('#09090b', '#fafafa')};
        background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
        width: 100%;
        height: 100%;
        border: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
        border-radius: 6px;
        padding: 0 12px 0 36px;
        font-family: 'Geist Sans', sans-serif;
        font-size: 13px;
        transition: all 0.15s ease;
      }

      .searchbox input::placeholder {
        color: ${cssManager.bdTheme('#71717a', '#71717a')};
      }

      .searchbox input:focus {
        outline: none;
        border-color: ${cssManager.bdTheme('#3b82f6', '#3b82f6')};
        box-shadow: 0 0 0 3px ${cssManager.bdTheme('rgba(59, 130, 246, 0.1)', 'rgba(59, 130, 246, 0.1)')};
      }

      .searchbox input:focus ~ .search-icon,
      .search-wrapper:has(input:focus) .search-icon {
        color: ${cssManager.bdTheme('#3b82f6', '#3b82f6')};
      }

      .bottomShadow {
        position: absolute;
        width: 100%;
        height: 24px;
        bottom: 48px;
        background: ${cssManager.bdTheme(
          'linear-gradient(180deg, transparent 0%, #fafafa 100%)',
          'linear-gradient(180deg, transparent 0%, #0a0a0a 100%)'
        )};
        pointer-events: none;
        opacity: 0.8;
      }

      .topShadow {
        position: absolute;
        width: 100%;
        height: 24px;
        top: 48px;
        background: ${cssManager.bdTheme(
          'linear-gradient(0deg, transparent 0%, #fafafa 100%)',
          'linear-gradient(0deg, transparent 0%, #0a0a0a 100%)'
        )};
        pointer-events: none;
        opacity: 0.8;
      }
    `,
  ];

  // RENDER
  public render(): TemplateResult {
    const filteredEntries = this.getFilteredEntries();
    const groupedEntries = this.groupEntriesByDate(filteredEntries);

    return html`
      ${domtools.elementBasic.styles}
      <style></style>
      <div class="maincontainer">
        <div class="topbar">
          <div class="heading">Activity Log</div>
        </div>
        <div class="activityContainer">
          ${filteredEntries.length > 0
            ? html`<div class="streamingIndicator">Live Updates</div>`
            : ''}

          ${filteredEntries.length === 0
            ? html`<div class="empty-state">No activity entries</div>`
            : groupedEntries.map(
                (group) => html`
                  <div class="date-separator">${group.label}</div>
                  ${group.entries.map((entry) => this.renderActivityEntry(entry))}
                `
              )}
        </div>
        <div class="searchbox">
          <div class="search-wrapper">
            <dees-icon class="search-icon" .icon=${'lucide:search'}></dees-icon>
            <input
              type="text"
              placeholder="Search activities, users..."
              .value=${this.searchQuery}
              @input=${this.handleSearchInput}
            />
          </div>
        </div>
        <div class="topShadow"></div>
        <div class="bottomShadow"></div>
      </div>
    `;
  }

  private renderActivityEntry(entry: IActivityEntry): TemplateResult {
    const timestamp = entry.timestamp || new Date();
    const timeStr = this.formatTime(timestamp);
    const iconName = entry.iconName || this.getIconForType(entry.type);

    return html`
      <div
        class="activityentry"
        @contextmenu=${(e: MouseEvent) => this.handleContextMenu(e, entry)}
      >
        <span class="timestamp">${timeStr}</span>
        <div class="activity-icon ${entry.type}">
          <dees-icon .icon=${iconName}></dees-icon>
        </div>
        <div class="activity-text">
          <span class="activity-user">${entry.user}</span> ${entry.message}
        </div>
      </div>
    `;
  }

  // API METHODS
  public add(entry: IActivityEntry): void {
    const newEntry: IActivityEntry = {
      ...entry,
      id: entry.id || this.generateId(),
      timestamp: entry.timestamp || new Date(),
    };
    this.entries = [newEntry, ...this.entries];
    this.entries$.next(this.entries);
  }

  public addMany(entries: IActivityEntry[]): void {
    const newEntries = entries.map((entry) => ({
      ...entry,
      id: entry.id || this.generateId(),
      timestamp: entry.timestamp || new Date(),
    }));
    this.entries = [...newEntries.reverse(), ...this.entries];
    this.entries$.next(this.entries);
  }

  public clear(): void {
    this.entries = [];
    this.entries$.next(this.entries);
  }

  public getEntries(): IActivityEntry[] {
    return [...this.entries];
  }

  public filter(criteria: { user?: string; type?: IActivityEntry['type'] }): IActivityEntry[] {
    return this.entries.filter((entry) => {
      if (criteria.user && entry.user !== criteria.user) return false;
      if (criteria.type && entry.type !== criteria.type) return false;
      return true;
    });
  }

  public search(query: string): IActivityEntry[] {
    const lowerQuery = query.toLowerCase();
    return this.entries.filter(
      (entry) =>
        entry.message.toLowerCase().includes(lowerQuery) ||
        entry.user.toLowerCase().includes(lowerQuery)
    );
  }

  // PRIVATE HELPERS
  private generateId(): string {
    return `activity-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
  }

  private getFilteredEntries(): IActivityEntry[] {
    let result = this.entries;

    if (this.searchQuery) {
      const lowerQuery = this.searchQuery.toLowerCase();
      result = result.filter(
        (entry) =>
          entry.message.toLowerCase().includes(lowerQuery) ||
          entry.user.toLowerCase().includes(lowerQuery)
      );
    }

    if (this.filterCriteria.user || this.filterCriteria.type) {
      result = result.filter((entry) => {
        if (this.filterCriteria.user && entry.user !== this.filterCriteria.user) return false;
        if (this.filterCriteria.type && entry.type !== this.filterCriteria.type) return false;
        return true;
      });
    }

    return result;
  }

  private groupEntriesByDate(
    entries: IActivityEntry[]
  ): Array<{ label: string; entries: IActivityEntry[] }> {
    const groups: Map<string, IActivityEntry[]> = new Map();
    const today = new Date();
    const yesterday = new Date(today);
    yesterday.setDate(yesterday.getDate() - 1);

    for (const entry of entries) {
      const date = entry.timestamp || new Date();
      let label: string;

      if (this.isSameDay(date, today)) {
        label = 'Today';
      } else if (this.isSameDay(date, yesterday)) {
        label = 'Yesterday';
      } else {
        label = date.toLocaleDateString('en-US', {
          month: 'short',
          day: 'numeric',
          year: date.getFullYear() !== today.getFullYear() ? 'numeric' : undefined,
        });
      }

      if (!groups.has(label)) {
        groups.set(label, []);
      }
      groups.get(label)!.push(entry);
    }

    return Array.from(groups.entries()).map(([label, entries]) => ({
      label,
      entries,
    }));
  }

  private isSameDay(date1: Date, date2: Date): boolean {
    return (
      date1.getFullYear() === date2.getFullYear() &&
      date1.getMonth() === date2.getMonth() &&
      date1.getDate() === date2.getDate()
    );
  }

  private formatTime(date: Date): string {
    return date.toLocaleTimeString('en-US', {
      hour: '2-digit',
      minute: '2-digit',
      hour12: false,
    });
  }

  private getIconForType(type: IActivityEntry['type']): string {
    const icons: Record<IActivityEntry['type'], string> = {
      login: 'lucide:logIn',
      logout: 'lucide:logOut',
      view: 'lucide:eye',
      create: 'lucide:plus',
      update: 'lucide:edit',
      delete: 'lucide:trash2',
      custom: 'lucide:activity',
    };
    return icons[type] || icons.custom;
  }

  private handleSearchInput(e: InputEvent): void {
    const target = e.target as HTMLInputElement;
    this.searchQuery = target.value;
  }

  private handleContextMenu(e: MouseEvent, entry: IActivityEntry): void {
    e.preventDefault();
    DeesContextmenu.openContextMenuWithOptions(e, [
      {
        name: 'Copy activity',
        iconName: 'lucide:copy',
        action: async () => {
          await navigator.clipboard.writeText(`${entry.user} ${entry.message}`);
        },
      },
      {
        name: 'Filter by user',
        iconName: 'lucide:user',
        action: async () => {
          this.filterCriteria = { user: entry.user };
        },
      },
      {
        name: 'Filter by type',
        iconName: 'lucide:filter',
        action: async () => {
          this.filterCriteria = { type: entry.type };
        },
      },
      {
        name: 'Clear filters',
        iconName: 'lucide:x',
        action: async () => {
          this.filterCriteria = {};
          this.searchQuery = '';
        },
      },
    ]);
  }
}
