import { Injectable, computed, inject, signal } from '@angular/core';
import { take } from 'rxjs/operators';
import { AdminReview, AdminReviewListFilters, AdminReviewStatus } from '../models/admin-review.model';
import { AdminReport, AdminReportStatus } from '../models/admin-report.model';
import { ADMIN_MODERATION_GATEWAY } from '../services/admin-moderation-gateway.token';
import { LocalStorageService } from '../../../../core/storage/local-storage.service';

export type AdminModerationViewMode = 'table' | 'cards';
export type AdminModerationDensity = 'comfortable' | 'compact';

export const ALL_REVIEW_COLUMNS = ['product', 'rating', 'status', 'reports', 'created'] as const;
export type AdminReviewColumn = typeof ALL_REVIEW_COLUMNS[number];

export interface AdminReviewHealth {
  hasRating: boolean;
  hasText: boolean;
  hasMedia: boolean;
  isModerated: boolean;
  reportStatusClear: boolean;
  isVisible: boolean;
  completionPercent: number;
}

export interface AdminModerationDashboardStats {
  pending: number;
  approved: number;
  rejected: number;
  reported: number;
  spam: number;
  averageRating: number | null;
  recentActivity: { reviewId: string; productName: string; eventKey: string; status?: AdminReviewStatus; timestamp: string }[];
  moderationHealthPercent: number;
}

const VIEW_MODE_KEY = 'admin-moderation:view-mode';
const DENSITY_KEY = 'admin-moderation:density';
const COLUMNS_KEY = 'admin-moderation:visible-columns';

@Injectable({ providedIn: 'root' })
export class AdminModerationFacade {
  private readonly gateway = inject(ADMIN_MODERATION_GATEWAY);
  private readonly localStorage = inject(LocalStorageService);

  readonly filters = signal<AdminReviewListFilters>({ search: '', status: 'all', rating: 'all', page: 1, pageSize: 10 });
  readonly reviews = signal<AdminReview[]>([]);
  readonly total = signal(0);
  readonly loading = signal(false);
  readonly selected = signal<AdminReview | null>(null);
  readonly reports = signal<AdminReport[]>([]);
  readonly reportsLoading = signal(false);
  readonly reportsError = signal(false);

  readonly viewMode = signal<AdminModerationViewMode>((this.localStorage.getItem(VIEW_MODE_KEY) as AdminModerationViewMode) || 'table');
  readonly density = signal<AdminModerationDensity>((this.localStorage.getItem(DENSITY_KEY) as AdminModerationDensity) || 'comfortable');
  readonly visibleColumns = signal<AdminReviewColumn[]>(this.localStorage.getJSON<AdminReviewColumn[]>(COLUMNS_KEY) ?? [...ALL_REVIEW_COLUMNS]);
  readonly selectedIds = signal<string[]>([]);
  readonly dashboardStats = signal<AdminModerationDashboardStats | null>(null);

  setViewMode(mode: AdminModerationViewMode): void {
    this.viewMode.set(mode);
    this.localStorage.setItem(VIEW_MODE_KEY, mode);
  }

  setDensity(density: AdminModerationDensity): void {
    this.density.set(density);
    this.localStorage.setItem(DENSITY_KEY, density);
  }

  setColumnVisible(column: AdminReviewColumn, visible: boolean): void {
    const next = visible ? [...new Set([...this.visibleColumns(), column])] : this.visibleColumns().filter(c => c !== column);
    this.visibleColumns.set(next);
    this.localStorage.setJSON(COLUMNS_KEY, next);
  }

  toggleSelection(id: string, checked: boolean): void {
    this.selectedIds.update(current => checked ? [...new Set([...current, id])] : current.filter(item => item !== id));
  }

  toggleAll(checked: boolean): void {
    this.selectedIds.set(checked ? this.reviews().map(review => review.id) : []);
  }

  clearSelection(): void {
    this.selectedIds.set([]);
  }

  loadList(): void {
    this.loading.set(true);
    this.gateway.loadReviews(this.filters()).pipe(take(1)).subscribe({
      next: result => {
        this.reviews.set(result.items);
        this.total.set(result.total);
        this.loading.set(false);
      },
      error: () => {
        this.reviews.set([]);
        this.total.set(0);
        this.loading.set(false);
      }
    });
  }

  updateFilters(patch: Partial<AdminReviewListFilters>): void {
    this.filters.update(current => ({ ...current, ...patch, page: patch.page ?? 1 }));
    this.loadList();
  }

  loadDetail(id: string): void {
    this.gateway.loadReview(id).pipe(take(1)).subscribe({ next: review => this.selected.set(review) });
  }

  setStatus(id: string, status: AdminReviewStatus, note = ''): void {
    this.gateway.setReviewStatus(id, status, note).pipe(take(1)).subscribe({ next: review => this.selected.set(review) });
  }

  setVisible(id: string, visible: boolean): void {
    this.gateway.setReviewVisible(id, visible).pipe(take(1)).subscribe({ next: review => this.selected.set(review) });
  }

  setPinned(id: string, pinned: boolean): void {
    this.gateway.setReviewPinned(id, pinned).pipe(take(1)).subscribe({ next: review => this.selected.set(review) });
  }

  setFeatured(id: string, featured: boolean): void {
    this.gateway.setReviewFeatured(id, featured).pipe(take(1)).subscribe({ next: review => this.selected.set(review) });
  }

  addNote(id: string, note: string): void {
    if (!note.trim()) return;
    this.gateway.addModeratorNote(id, note.trim()).pipe(take(1)).subscribe({ next: review => this.selected.set(review) });
  }

  applyBulkStatus(status: AdminReviewStatus): void {
    const ids = [...this.selectedIds()];
    ids.forEach(id => this.gateway.setReviewStatus(id, status, `Bulk status change to ${status}`).pipe(take(1)).subscribe());
    this.clearSelection();
    this.loadList();
    this.loadDashboardStats();
  }

  applyBulkVisible(visible: boolean): void {
    const ids = [...this.selectedIds()];
    ids.forEach(id => this.gateway.setReviewVisible(id, visible).pipe(take(1)).subscribe());
    this.clearSelection();
    this.loadList();
  }

  applyBulkDelete(): void {
    const ids = [...this.selectedIds()];
    ids.forEach(id => this.gateway.deleteReview(id).pipe(take(1)).subscribe());
    this.clearSelection();
    this.loadList();
    this.loadDashboardStats();
  }

  exportSelectedAsCsv(): void {
    const selected = new Set(this.selectedIds());
    const rows = this.reviews().filter(review => selected.has(review.id));
    const header = 'Product,Customer,Rating,Status,Reports,Created At';
    const lines = rows.map(review => [review.productName, review.customerName, review.rating, review.status, review.reportCount, review.createdAt].join(','));
    const csv = [header, ...lines].join('\n');
    const blob = new Blob([csv], { type: 'text/csv' });
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = 'reviews-export.csv';
    link.click();
    URL.revokeObjectURL(url);
  }

  loadReports(): void {
    this.reportsLoading.set(true);
    this.reportsError.set(false);
    this.gateway.loadReports().pipe(take(1)).subscribe({
      next: reports => { this.reports.set(reports); this.reportsLoading.set(false); },
      error: () => { this.reports.set([]); this.reportsLoading.set(false); this.reportsError.set(true); }
    });
  }

  setReportStatus(id: string, status: AdminReportStatus): void {
    this.gateway.setReportStatus(id, status).pipe(take(1)).subscribe({ next: () => this.loadReports() });
  }

  health(review: AdminReview): AdminReviewHealth {
    const hasRating = review.rating > 0;
    const hasText = review.text.trim().length > 0;
    const hasMedia = review.photos.length > 0;
    const isModerated = review.status !== 'pending';
    const reportStatusClear = review.reportCount === 0;
    const isVisible = review.visible;
    const checks = [hasRating, hasText, hasMedia, isModerated, reportStatusClear, isVisible];
    const completionPercent = Math.round((checks.filter(Boolean).length / checks.length) * 100);
    return { hasRating, hasText, hasMedia, isModerated, reportStatusClear, isVisible, completionPercent };
  }

  /** Dashboard reflects the whole review queue, not just the current filtered/paginated page. */
  loadDashboardStats(): void {
    this.gateway.loadReviews({ search: '', status: 'all', rating: 'all', page: 1, pageSize: 100000 }).pipe(take(1))
      .subscribe({ next: result => this.dashboardStats.set(this.computeDashboardStats(result.items)) });
  }

  private computeDashboardStats(reviews: AdminReview[]): AdminModerationDashboardStats {
    const rated = reviews.filter(review => review.rating > 0);
    const averageRating = rated.length > 0 ? Math.round((rated.reduce((sum, review) => sum + review.rating, 0) / rated.length) * 10) / 10 : null;

    const recentActivity = reviews
      .flatMap(review => review.timeline.map(entry => ({ reviewId: review.id, productName: review.productName, eventKey: entry.eventKey, status: entry.status, timestamp: entry.timestamp })))
      .sort((a, b) => b.timestamp.localeCompare(a.timestamp))
      .slice(0, 8);

    const moderated = reviews.filter(review => review.status !== 'pending').length;
    const moderationHealthPercent = reviews.length > 0 ? Math.round((moderated / reviews.length) * 100) : 100;

    return {
      pending: reviews.filter(review => review.status === 'pending').length,
      approved: reviews.filter(review => review.status === 'approved').length,
      rejected: reviews.filter(review => review.status === 'rejected').length,
      reported: reviews.filter(review => review.reportCount > 0).length,
      spam: reviews.filter(review => review.status === 'spam').length,
      averageRating,
      recentActivity,
      moderationHealthPercent,
    };
  }
}
