import { Component, OnInit, inject, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { MatCardModule } from '@angular/material/card';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatChipsModule } from '@angular/material/chips';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { PageHeaderComponent } from '../../../shared/components/page-header/page-header.component';
import { EmptyStateComponent } from '../../../shared/components/empty-state/empty-state.component';
import { AuditService } from '../services/audit.service';
import { AuditLogDto } from '../../../api/models';

@Component({
  selector: 'app-entity-trail',
  standalone: true,
  imports: [
    CommonModule,
    RouterModule,
    MatCardModule,
    MatButtonModule,
    MatIconModule,
    MatChipsModule,
    MatProgressSpinnerModule,
    PageHeaderComponent,
    EmptyStateComponent,
  ],
  template: `
    <div class="page-container">
      <app-page-header
        [title]="'Audit Trail'"
        [subtitle]="entityType() + ' / ' + entityId()"
      >
        <button mat-button routerLink="/audit">
          <mat-icon>arrow_back</mat-icon>
          Back to Logs
        </button>
      </app-page-header>

      @if (loading()) {
        <div class="loading-container">
          <mat-spinner diameter="48"></mat-spinner>
        </div>
      } @else if (events().length === 0) {
        <app-empty-state
          icon="history"
          title="No trail found"
          message="No audit events found for this entity."
        />
      } @else {
        <div class="timeline">
          @for (event of events(); track event.id) {
            <div class="timeline-item">
              <div class="timeline-marker" [class]="getActionClass(event.action)">
                <mat-icon>{{ getActionIcon(event.action) }}</mat-icon>
              </div>
              <mat-card class="timeline-content">
                <div class="event-header">
                  <mat-chip [class]="getActionChipClass(event.action)">
                    {{ event.action }}
                  </mat-chip>
                  <span class="timestamp">{{ event.timestamp | date: 'medium' }}</span>
                </div>
                <div class="event-actor">
                  <span class="actor-type">{{ event.actorType }}</span>
                  <span class="actor-id">{{ event.actorId }}</span>
                </div>
                @if (event.changes && hasChanges(event.changes)) {
                  <div class="event-changes">
                    <h4>Changes</h4>
                    <div class="changes-list">
                      @for (key of getChangeKeys(event.changes); track key) {
                        <div class="change-item">
                          <span class="change-key">{{ key }}</span>
                          <span class="change-value">{{ event.changes[key] | json }}</span>
                        </div>
                      }
                    </div>
                  </div>
                }
                @if (event.ipAddress) {
                  <div class="event-meta">
                    <span>IP: {{ event.ipAddress }}</span>
                  </div>
                }
              </mat-card>
            </div>
          }
        </div>
      }
    </div>
  `,
  styles: [
    `
      .loading-container {
        display: flex;
        justify-content: center;
        padding: 48px;
      }

      .timeline {
        position: relative;
        padding-left: 40px;
        max-width: 800px;

        &::before {
          content: '';
          position: absolute;
          left: 16px;
          top: 0;
          bottom: 0;
          width: 2px;
          background-color: #e0e0e0;
        }
      }

      .timeline-item {
        position: relative;
        margin-bottom: 24px;
      }

      .timeline-marker {
        position: absolute;
        left: -40px;
        top: 16px;
        width: 32px;
        height: 32px;
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        background-color: #e0e0e0;
        z-index: 1;

        mat-icon {
          font-size: 16px;
          width: 16px;
          height: 16px;
          color: white;
        }

        &.create {
          background-color: #4caf50;
        }
        &.update {
          background-color: #2196f3;
        }
        &.delete {
          background-color: #f44336;
        }
        &.approve {
          background-color: #4caf50;
        }
        &.reject {
          background-color: #f44336;
        }
        &.submit {
          background-color: #ff9800;
        }
      }

      .timeline-content {
        padding: 16px;
      }

      .event-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 12px;
      }

      .timestamp {
        font-size: 0.875rem;
        color: rgba(0, 0, 0, 0.54);
      }

      .event-actor {
        display: flex;
        gap: 8px;
        margin-bottom: 12px;
      }

      .actor-type {
        font-weight: 500;
      }

      .actor-id {
        font-family: monospace;
        font-size: 0.875rem;
        color: rgba(0, 0, 0, 0.54);
      }

      .event-changes {
        background-color: #fafafa;
        padding: 12px;
        border-radius: 8px;
        margin-top: 12px;

        h4 {
          margin: 0 0 8px;
          font-size: 0.875rem;
          font-weight: 500;
        }
      }

      .changes-list {
        display: flex;
        flex-direction: column;
        gap: 4px;
      }

      .change-item {
        display: flex;
        gap: 8px;
        font-size: 0.875rem;
      }

      .change-key {
        font-weight: 500;
        color: rgba(0, 0, 0, 0.54);
      }

      .change-value {
        font-family: monospace;
        word-break: break-all;
      }

      .event-meta {
        margin-top: 12px;
        font-size: 0.75rem;
        color: rgba(0, 0, 0, 0.38);
      }

      .action-create {
        background-color: #c8e6c9 !important;
        color: #2e7d32 !important;
      }

      .action-update {
        background-color: #bbdefb !important;
        color: #1565c0 !important;
      }

      .action-delete {
        background-color: #ffcdd2 !important;
        color: #c62828 !important;
      }
    `,
  ],
})
export class EntityTrailComponent implements OnInit {
  private readonly route = inject(ActivatedRoute);
  private readonly router = inject(Router);
  private readonly auditService = inject(AuditService);

  readonly loading = signal(true);
  readonly events = signal<AuditLogDto[]>([]);
  readonly entityType = signal('');
  readonly entityId = signal('');

  ngOnInit(): void {
    const type = this.route.snapshot.paramMap.get('entityType');
    const id = this.route.snapshot.paramMap.get('entityId');

    if (!type || !id) {
      this.router.navigate(['/audit']);
      return;
    }

    this.entityType.set(type);
    this.entityId.set(id);
    this.loadTrail();
  }

  private loadTrail(): void {
    this.auditService.getEntityTrail(this.entityType(), this.entityId()).subscribe({
      next: (trail) => {
        this.events.set(trail?.events ?? []);
        this.loading.set(false);
      },
      error: () => {
        this.loading.set(false);
      },
    });
  }

  getActionIcon(action: string): string {
    switch (action) {
      case 'CREATE':
        return 'add';
      case 'UPDATE':
        return 'edit';
      case 'DELETE':
        return 'delete';
      case 'APPROVE':
        return 'check';
      case 'REJECT':
        return 'close';
      case 'SUBMIT':
        return 'send';
      default:
        return 'info';
    }
  }

  getActionClass(action: string): string {
    return action.toLowerCase();
  }

  getActionChipClass(action: string): string {
    return `action-${action.toLowerCase()}`;
  }

  hasChanges(changes: Record<string, unknown>): boolean {
    return Object.keys(changes).length > 0;
  }

  getChangeKeys(changes: Record<string, unknown>): string[] {
    return Object.keys(changes);
  }
}
