import { Component, inject, OnInit, signal, computed } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ActivatedRoute, Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { Store } from '@ngrx/store';
import { forkJoin } from 'rxjs';
import { ButtonModule } from 'primeng/button';
import { TagModule } from 'primeng/tag';
import { TableModule } from 'primeng/table';
import { ChartModule } from 'primeng/chart';
import { ToastModule } from 'primeng/toast';
import { TooltipModule } from 'primeng/tooltip';
import { MessageService } from 'primeng/api';
import { ProductService } from '../../core/services/product.service';
import { StockBalanceService } from '../../core/services/stock-balance.service';
import { AttachmentService, Attachment } from '../../core/services/attachment.service';
import { selectAllUnits } from '../../core/store';
import { Product, ProductPrice, ProductVariant, ProductUnit, ProductSerial } from '../../core/models/product.model';
import { StockBalance, StockCardEntry } from '../../core/models/inventory.model';
import { environment } from '../../../environments/environment';

@Component({
  selector: 'app-product-detail',
  standalone: true,
  imports: [
    CommonModule, TranslateModule,
    ButtonModule, TagModule, TableModule, ChartModule,
    ToastModule, TooltipModule,
  ],
  providers: [MessageService],
  templateUrl: './product-detail.component.html',
  styleUrl: './product-detail.component.scss',
})
export class ProductDetailComponent implements OnInit {
  private route = inject(ActivatedRoute);
  private router = inject(Router);
  private http = inject(HttpClient);
  private translate = inject(TranslateService);
  private store = inject(Store);
  private productService = inject(ProductService);
  private stockBalanceService = inject(StockBalanceService);
  private attachmentService = inject(AttachmentService);

  loading = signal(true);
  product = signal<Product | null>(null);
  prices = signal<ProductPrice[]>([]);
  variants = signal<ProductVariant[]>([]);
  productUnits = signal<ProductUnit[]>([]);
  balances = signal<StockBalance[]>([]);
  entries = signal<StockCardEntry[]>([]);
  serials = signal<ProductSerial[]>([]);
  gallery = signal<Attachment[]>([]);
  galleryBlobUrls = signal<Record<number, string>>({});
  mainImageBlob = signal<string | null>(null);
  selectedImage = signal<string | null>(null);

  private unitMap = new Map<number, string>();

  // Computed serial stats
  serialsAvailable = computed(() => this.serials().filter(s => s.status.value === 'available').length);
  serialsSold = computed(() => this.serials().filter(s => s.status.value === 'sold').length);
  isSerialTracked = computed(() => this.product()?.tracking_type?.value === 'serial');

  // Computed prices
  purchasePrice = computed(() => parseFloat(this.product()?.purchase_price || '0'));
  salePrice = computed(() => parseFloat(this.product()?.sale_price || '0'));
  minSalePrice = computed(() => parseFloat(this.product()?.min_sale_price || '0'));
  wholesalePrice = computed(() => {
    const p = this.prices().find(pr => this.getPriceTypeValue(pr) === 'wholesale');
    return p ? parseFloat(p.price) : 0;
  });
  halfWholesalePrice = computed(() => {
    const p = this.prices().find(pr => this.getPriceTypeValue(pr) === 'half_wholesale');
    return p ? parseFloat(p.price) : 0;
  });

  // Computed inventory stats
  totalStock = computed(() => this.balances().reduce((s, b) => s + (+b.quantity || 0), 0));
  totalIn = computed(() => this.entries().reduce((s, e) => s + (+e.quantity_in || 0), 0));
  totalOut = computed(() => this.entries().reduce((s, e) => s + (+e.quantity_out || 0), 0));
  avgCost = computed(() => {
    const bals = this.balances();
    if (!bals.length) return 0;
    const totalVal = bals.reduce((s, b) => s + (+b.total_value || 0), 0);
    const totalQty = bals.reduce((s, b) => s + (+b.quantity || 0), 0);
    return totalQty > 0 ? totalVal / totalQty : 0;
  });
  totalValue = computed(() => this.balances().reduce((s, b) => s + (+b.total_value || 0), 0));

  // Charts
  stockTrendData = signal<any>(null);
  stockTrendOptions: any = {
    responsive: true,
    maintainAspectRatio: false,
    plugins: { legend: { display: false } },
    scales: {
      x: { grid: { display: false } },
      y: { beginAtZero: true, grid: { color: 'rgba(0,0,0,0.05)' } },
    },
  };

  warehouseChartData = signal<any>(null);
  warehouseChartOptions: any = {
    indexAxis: 'y',
    responsive: true,
    maintainAspectRatio: false,
    plugins: { legend: { display: false } },
    scales: {
      x: { beginAtZero: true, grid: { color: 'rgba(0,0,0,0.05)' } },
      y: { grid: { display: false } },
    },
  };

  ngOnInit(): void {
    const id = +this.route.snapshot.paramMap.get('id')!;
    this.store.select(selectAllUnits).subscribe(units => {
      units.forEach(u => this.unitMap.set(u.id, u.name || u.name_ar));
    });
    this.loadData(id);
  }

  private loadData(id: number): void {
    this.loading.set(true);
    forkJoin({
      product: this.productService.getById(id),
      prices: this.productService.listPrices(id),
      variants: this.productService.listVariants(id),
      units: this.productService.listProductUnits(id),
      balances: this.stockBalanceService.listFiltered({ product_id: id }),
      entries: this.stockBalanceService.getStockCardFilteredAll(id),
      gallery: this.attachmentService.list(1, 100, { attachable_type: 'product', attachable_id: id }),
      serials: this.productService.listSerials(id, {}),
    }).subscribe({
      next: (res) => {
        this.product.set(res.product.data);
        this.prices.set(res.prices.data || []);
        this.variants.set(res.variants.data || []);
        this.productUnits.set(res.units.data || []);
        this.balances.set(res.balances.data || []);
        this.entries.set(res.entries.data || []);
        this.gallery.set(res.gallery.data || []);
        this.serials.set(res.serials.data || []);

        // Load main image
        if (res.product.data.image) {
          this.selectedImage.set(res.product.data.image);
          this.loadImageAsBlob(res.product.data.image, url => this.mainImageBlob.set(url));
        }

        // Load gallery blobs
        for (const att of (res.gallery.data || [])) {
          const url = `${environment.apiUrl}/core/attachments/${att.id}/download`;
          this.loadImageAsBlob(url, blobUrl => {
            this.galleryBlobUrls.update(m => ({ ...m, [att.id]: blobUrl }));
          });
        }

        this.buildCharts();
        this.loading.set(false);
      },
      error: () => {
        this.loading.set(false);
      },
    });
  }

  private loadImageAsBlob(url: string, onLoad: (blobUrl: string) => void): void {
    this.http.get(url, { responseType: 'blob' }).subscribe({
      next: (blob) => onLoad(URL.createObjectURL(blob)),
      error: () => {},
    });
  }

  selectGalleryImage(attachment: Attachment): void {
    const blobUrl = this.galleryBlobUrls()[attachment.id];
    if (blobUrl) {
      this.mainImageBlob.set(blobUrl);
    }
  }

  private buildCharts(): void {
    const ents = this.entries();
    if (ents.length) {
      const sorted = [...ents].sort((a, b) => a.date.localeCompare(b.date) || a.id - b.id);
      this.stockTrendData.set({
        labels: sorted.map(e => e.date),
        datasets: [{
          label: this.translate.instant('PRODUCTS.TOTAL_STOCK'),
          data: sorted.map(e => +e.balance_after),
          fill: true,
          borderColor: '#6366f1',
          backgroundColor: 'rgba(99,102,241,0.1)',
          tension: 0.4,
          pointRadius: 2,
          pointHoverRadius: 5,
        }],
      });
    }

    const bals = this.balances();
    if (bals.length) {
      this.warehouseChartData.set({
        labels: bals.map(b => b.warehouse_name),
        datasets: [{
          label: this.translate.instant('PRODUCTS.QTY_BY_WAREHOUSE'),
          data: bals.map(b => +b.quantity),
          backgroundColor: '#6366f1',
          borderRadius: 6,
        }],
      });
    }
  }

  getUnitName(unitId: number | null): string {
    if (!unitId) return '—';
    return this.unitMap.get(unitId) || '—';
  }

  getPriceTypeValue(price: ProductPrice): string {
    return typeof price.price_type === 'object' ? price.price_type.value : price.price_type;
  }

  getPriceTypeLabel(price: ProductPrice): string {
    return typeof price.price_type === 'object' ? price.price_type.label : price.price_type;
  }

  getVariantAttributeText(variant: ProductVariant): string {
    if (!variant.attributes) return '—';
    return Object.entries(variant.attributes).map(([k, v]) => `${k}: ${v}`).join(' | ');
  }

  getMovementSeverity(type: string): 'success' | 'danger' | 'info' | 'warn' | 'secondary' {
    const lower = type.toLowerCase();
    if (lower.includes('receipt') || lower.includes('opening')) return 'success';
    if (lower.includes('issue')) return 'danger';
    if (lower.includes('transfer')) return 'info';
    return 'secondary';
  }

  getSerialStatusSeverity(status: string): 'success' | 'warn' | 'danger' | 'info' {
    switch(status) {
      case 'available': return 'success';
      case 'sold': return 'danger';
      case 'reserved': return 'warn';
      default: return 'info';
    }
  }

  goBack(): void {
    this.router.navigate(['/core/products']);
  }

  editProduct(): void {
    // Navigate back to products page — the edit is handled via dialog there
    this.router.navigate(['/core/products']);
  }
}
