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;
  public static demoGroup = 'App UI';

  // 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`
      :host {
        /* CSS Variables aligned with secondary menu */
        --activitylog-bg: ${cssManager.bdTheme('#fafafa', '#0a0a0a')};
        --activitylog-fg: ${cssManager.bdTheme('#525252', '#a3a3a3')};
        --activitylog-fg-muted: ${cssManager.bdTheme('#737373', '#737373')};
        --activitylog-fg-active: ${cssManager.bdTheme('#0a0a0a', '#fafafa')};
        --activitylog-border: ${cssManager.bdTheme('#e5e5e5', '#1a1a1a')};
        --activitylog-hover: ${cssManager.bdTheme('rgba(0, 0, 0, 0.04)', 'rgba(255, 255, 255, 0.06)')};
        --activitylog-accent: ${cssManager.bdTheme('#78716c', '#b5a99a')};

        color: var(--activitylog-fg);
        position: relative;
        display: block;
        width: 100%;
        height: 100%;
        background: var(--activitylog-bg);
        font-family: 'Geist Sans', -apple-system, BlinkMacSystemFont, sans-serif;
        border-left: 1px solid var(--activitylog-border);
        cursor: default;
        overflow: hidden;
      }

      .maincontainer {
        position: absolute;
        top: 0px;
        left: 0px;
        height: 100%;
        width: 280px;
      }

      /* Header with streaming indicator */
      .topbar {
        position: absolute;
        top: 0px;
        height: 48px;
        width: 100%;
        padding: 0px 12px;
        background: var(--activitylog-bg);
        border-bottom: 1px solid var(--activitylog-border);
        display: flex;
        align-items: center;
        justify-content: space-between;
        box-sizing: border-box;
      }

      .topbar .heading {
        font-weight: 600;
        font-size: 14px;
        color: var(--activitylog-fg-active);
      }

      .live-indicator {
        display: flex;
        align-items: center;
        gap: 6px;
        font-size: 10px;
        font-weight: 500;
        text-transform: uppercase;
        letter-spacing: 0.05em;
        color: var(--activitylog-fg-muted);
      }

      .live-indicator .dot {
        width: 6px;
        height: 6px;
        background: ${cssManager.bdTheme('#22c55e', '#22c55e')};
        border-radius: 50%;
        animation: pulse 2s ease-in-out infinite;
      }

      @keyframes pulse {
        0%, 100% { opacity: 0.5; transform: scale(0.9); }
        50% { opacity: 1; transform: scale(1.1); }
      }

      /* Activity container */
      .activityContainer {
        position: absolute;
        top: 48px;
        bottom: 48px;
        width: 100%;
        padding: 8px 0;
        overflow-y: auto;
        overscroll-behavior: contain;
        scrollbar-width: thin;
        scrollbar-color: ${cssManager.bdTheme('#d4d4d4', '#333333')} transparent;
      }

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

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

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

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

      .empty-state {
        font-size: 13px;
        text-align: center;
        padding: 40px 16px;
        color: var(--activitylog-fg-muted);
      }

      /* Date separator - warm taupe styling */
      .date-separator {
        padding: 12px 12px 6px;
        font-size: 10px;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.5px;
        color: var(--activitylog-accent);
        position: sticky;
        top: 0;
        z-index: 1;
        background: var(--activitylog-bg);
      }

      /* Activity entry - modern stacked layout */
      .activityentry {
        font-size: 12px;
        padding: 8px 12px;
        margin: 2px 4px;
        border-radius: 6px;
        transition: background 0.15s ease;
        display: flex;
        align-items: flex-start;
        gap: 10px;
        line-height: 1.4;
        animation: fadeIn 0.2s ease-out;
      }

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

      .activityentry:hover {
        background: var(--activitylog-hover);
      }

      .activity-icon {
        width: 28px;
        height: 28px;
        border-radius: 6px;
        background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.04)', 'rgba(255, 255, 255, 0.06)')};
        display: flex;
        align-items: center;
        justify-content: center;
        flex-shrink: 0;
        font-size: 13px;
        color: var(--activitylog-fg-muted);
        margin-top: 1px;
      }

      .activity-icon.login {
        background: ${cssManager.bdTheme('rgba(34, 197, 94, 0.08)', 'rgba(34, 197, 94, 0.12)')};
        color: ${cssManager.bdTheme('#16a34a', '#4ade80')};
      }

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

      .activity-icon.view {
        background: ${cssManager.bdTheme('rgba(59, 130, 246, 0.08)', 'rgba(59, 130, 246, 0.12)')};
        color: ${cssManager.bdTheme('#2563eb', '#60a5fa')};
      }

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

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

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

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

      .activity-content {
        flex: 1;
        min-width: 0;
        display: flex;
        flex-direction: column;
        gap: 2px;
      }

      .activity-header {
        display: flex;
        align-items: center;
        gap: 6px;
      }

      .activity-user {
        font-weight: 600;
        font-size: 12px;
        color: var(--activitylog-fg-active);
      }

      .activity-separator {
        color: var(--activitylog-fg-muted);
        font-size: 10px;
      }

      .timestamp {
        color: var(--activitylog-fg-muted);
        font-weight: 400;
        font-size: 11px;
        font-variant-numeric: tabular-nums;
        font-family: 'Geist Mono', monospace;
      }

      .activity-message {
        color: var(--activitylog-fg);
        font-size: 12px;
        line-height: 1.5;
        word-break: break-word;
      }

      /* Search box - refined styling */
      .searchbox {
        position: absolute;
        bottom: 0px;
        width: 100%;
        height: 48px;
        background: var(--activitylog-bg);
        border-top: 1px solid var(--activitylog-border);
        padding: 8px 12px;
        box-sizing: border-box;
      }

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

      .search-icon {
        position: absolute;
        left: 10px;
        top: 50%;
        transform: translateY(-50%);
        color: var(--activitylog-fg-muted);
        font-size: 13px;
        pointer-events: none;
        transition: color 0.15s ease;
      }

      .searchbox input {
        color: var(--activitylog-fg-active);
        background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.03)', 'rgba(255, 255, 255, 0.04)')};
        width: 100%;
        height: 100%;
        border: 1px solid ${cssManager.bdTheme('rgba(0, 0, 0, 0.08)', 'rgba(255, 255, 255, 0.08)')};
        border-radius: 6px;
        padding: 0 12px 0 34px;
        font-family: 'Geist Sans', sans-serif;
        font-size: 12px;
        transition: all 0.15s ease;
      }

      .searchbox input::placeholder {
        color: var(--activitylog-fg-muted);
      }

      .searchbox input:focus {
        outline: none;
        border-color: ${cssManager.bdTheme('rgba(0, 0, 0, 0.15)', 'rgba(255, 255, 255, 0.15)')};
        background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.02)', 'rgba(255, 255, 255, 0.06)')};
      }

      .search-wrapper:has(input:focus) .search-icon {
        color: var(--activitylog-fg);
      }
    `,
  ];

  // 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>
          ${filteredEntries.length > 0
            ? html`<div class="live-indicator"><span class="dot"></span>Live</div>`
            : ''}
        </div>
        <div class="activityContainer">
          ${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>
    `;
  }

  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)}
      >
        <div class="activity-icon ${entry.type}">
          <dees-icon .icon=${iconName}></dees-icon>
        </div>
        <div class="activity-content">
          <div class="activity-header">
            <span class="activity-user">${entry.user}</span>
            <span class="activity-separator">·</span>
            <span class="timestamp">${timeStr}</span>
          </div>
          <div class="activity-message">${entry.message}</div>
        </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 = '';
        },
      },
    ]);
  }
}
