import { Component, inject, OnInit, signal, computed } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { ButtonModule } from 'primeng/button';
import { SelectModule } from 'primeng/select';
import { TableModule } from 'primeng/table';
import { ToastModule } from 'primeng/toast';
import { ChartModule } from 'primeng/chart';
import { TagModule } from 'primeng/tag';
import { ToggleSwitchModule } from 'primeng/toggleswitch';
import { DatePickerModule } from 'primeng/datepicker';
import { MessageService } from 'primeng/api';
import { forkJoin } from 'rxjs';
import { BranchContextService } from '../../core/services/branch-context.service';
import { StockBalanceService } from '../../core/services/stock-balance.service';
import { WarehouseService } from '../../core/services/warehouse.service';
import { ProductService } from '../../core/services/product.service';
import { InventoryReportService, ProductCost, CostLayer } from '../../core/services/inventory-report.service';
import { StockBalance, StockCardEntry } from '../../core/models/inventory.model';
import { Warehouse } from '../../core/models/warehouse.model';
import { Product } from '../../core/models/product.model';

@Component({
  selector: 'app-stock-card',
  standalone: true,
  imports: [
    CommonModule, FormsModule, TranslateModule,
    ButtonModule, SelectModule, TableModule,
    ToastModule, ChartModule, TagModule, DatePickerModule, ToggleSwitchModule,
  ],
  providers: [MessageService],
  templateUrl: './stock-card.component.html',
  styleUrl: './stock-card.component.scss',
})
export class StockCardComponent implements OnInit {
  private route = inject(ActivatedRoute);
  private router = inject(Router);
  private translate = inject(TranslateService);
  private messageService = inject(MessageService);
  private branchContext = inject(BranchContextService);
  private stockBalanceService = inject(StockBalanceService);
  private warehouseService = inject(WarehouseService);
  private productService = inject(ProductService);
  private inventoryReportService = inject(InventoryReportService);

  productId = 0;
  variantId: number | null = null;
  variantName = '';
  private allowedWarehouseIds: number[] = [];
  product = signal<Product | null>(null);
  loading = signal(true);
  statsCollapsed = signal(true);
  entries = signal<StockCardEntry[]>([]);
  balances = signal<StockBalance[]>([]);
  warehouses = signal<Warehouse[]>([]);
  selectedWarehouseId = signal<number | null>(null);
  allEntries = signal<StockCardEntry[]>([]);

  // Cost data
  productCost = signal<ProductCost | null>(null);
  costLayers = signal<CostLayer[]>([]);
  showExhausted = signal(false);

  // Date range filter
  dateFrom = signal<Date | null>(null);
  dateTo = signal<Date | null>(null);
  activeDatePreset = signal<string>('all');

  // Computed stats
  currentBalance = 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
  balanceChartData = signal<any>(null);
  balanceChartOptions: 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)' } }
    }
  };

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

  movementChartData = signal<any>(null);
  movementChartOptions: any = {
    responsive: true,
    maintainAspectRatio: false,
    plugins: { legend: { position: 'bottom' } }
  };

  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 {
    this.productId = +this.route.snapshot.paramMap.get('productId')!;
    const qp = this.route.snapshot.queryParams;
    if (qp['variantId']) {
      this.variantId = +qp['variantId'];
      this.variantName = qp['variantName'] || '';
    }
    this.loadAll();
  }

  loadAll(): void {
    this.loading.set(true);
    forkJoin({
      product: this.productService.getById(this.productId),
      entries: this.stockBalanceService.getStockCardFilteredAll(this.productId),
      balances: this.stockBalanceService.listFiltered({ product_id: this.productId }),
      warehouses: this.warehouseService.listForCurrentBranch(),
    }).subscribe({
      next: (res) => {
        this.product.set(res.product.data);
        let entries = res.entries.data;
        let balances = res.balances.data;
        // Filter by variant if specified
        if (this.variantId) {
          entries = entries.filter(e => e.product_variant_id === this.variantId);
          balances = balances.filter(b => b.product_variant_id === this.variantId);
        }
        // Filter by user's branch warehouses
        this.warehouses.set(res.warehouses.data);
        this.allowedWarehouseIds = res.warehouses.data.map(w => w.id);
        if (this.branchContext.hasBranchRestriction()) {
          balances = balances.filter(b => this.allowedWarehouseIds.includes(b.warehouse_id));
          entries = entries.filter(e => this.allowedWarehouseIds.includes(e.warehouse_id));
        }
        this.allEntries.set(entries);
        this.entries.set(entries);
        this.balances.set(balances);
        this.buildCharts();
        this.loading.set(false);
        this.loadCostData();
      },
      error: (err) => {
        this.loading.set(false);
        this.showError(err);
      },
    });
  }

  loadCostData(): void {
    const variantId = this.variantId || undefined;
    this.inventoryReportService.getProductCost(this.productId, undefined, variantId).subscribe({
      next: (res) => this.productCost.set(res.data),
      error: () => {},
    });
    this.loadCostLayers();
  }

  loadCostLayers(): void {
    const variantId = this.variantId || undefined;
    this.inventoryReportService.getCostLayers(this.productId, undefined, variantId, this.showExhausted()).subscribe({
      next: (res) => this.costLayers.set(res.data),
      error: () => {},
    });
  }

  toggleExhausted(): void {
    this.showExhausted.update(v => !v);
    this.loadCostLayers();
  }

  onWarehouseFilter(warehouseId: number | null): void {
    this.selectedWarehouseId.set(warehouseId);
    this.reloadEntries();
  }

  setDatePreset(preset: string): void {
    this.activeDatePreset.set(preset);
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    switch (preset) {
      case 'today':
        this.dateFrom.set(new Date(today));
        this.dateTo.set(new Date(today));
        break;
      case 'week': {
        const weekStart = new Date(today);
        weekStart.setDate(today.getDate() - today.getDay());
        this.dateFrom.set(weekStart);
        this.dateTo.set(new Date(today));
        break;
      }
      case 'month': {
        const monthStart = new Date(today.getFullYear(), today.getMonth(), 1);
        this.dateFrom.set(monthStart);
        this.dateTo.set(new Date(today));
        break;
      }
      case 'all':
      default:
        this.dateFrom.set(null);
        this.dateTo.set(null);
        break;
    }
    this.reloadEntries();
  }

  onDateFromChange(date: Date | null): void {
    this.dateFrom.set(date);
    this.activeDatePreset.set('custom');
    this.reloadEntries();
  }

  onDateToChange(date: Date | null): void {
    this.dateTo.set(date);
    this.activeDatePreset.set('custom');
    this.reloadEntries();
  }

  entriesLoading = signal(false);

  private reloadEntries(): void {
    this.entriesLoading.set(true);
    const filters: any = {};
    if (this.selectedWarehouseId()) filters.warehouse_id = this.selectedWarehouseId();
    const from = this.dateFrom();
    const to = this.dateTo();
    if (from) filters.date_from = this.formatDate(from);
    if (to) filters.date_to = this.formatDate(to);

    this.stockBalanceService.getStockCardFilteredAll(this.productId, filters).subscribe({
      next: (res) => {
        let data = res.data;
        if (this.variantId) {
          data = data.filter(e => e.product_variant_id === this.variantId);
        }
        if (this.branchContext.hasBranchRestriction() && this.allowedWarehouseIds.length > 0) {
          data = data.filter(e => this.allowedWarehouseIds.includes(e.warehouse_id));
        }
        this.entries.set(data);
        this.buildCharts();
        this.entriesLoading.set(false);
      },
      error: (err) => {
        this.entriesLoading.set(false);
        this.showError(err);
      },
    });
  }

  private formatDate(d: Date): string {
    const y = d.getFullYear();
    const m = String(d.getMonth() + 1).padStart(2, '0');
    const day = String(d.getDate()).padStart(2, '0');
    return `${y}-${m}-${day}`;
  }

  buildCharts(): void {
    const ents = this.entries();
    if (!ents.length) {
      this.balanceChartData.set(null);
      this.monthlyChartData.set(null);
      this.movementChartData.set(null);
      this.warehouseChartData.set(null);
      return;
    }

    // 1. Balance over time (chronological)
    const sorted = [...ents].sort((a, b) => a.date.localeCompare(b.date) || a.id - b.id);
    this.balanceChartData.set({
      labels: sorted.map(e => e.date),
      datasets: [{
        label: this.translate.instant('INVENTORY.BALANCE'),
        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,
      }]
    });

    // 2. Monthly In vs Out
    const monthMap = new Map<string, { in: number; out: number }>();
    sorted.forEach(e => {
      const m = e.date.substring(0, 7);
      const cur = monthMap.get(m) || { in: 0, out: 0 };
      cur.in += +e.quantity_in || 0;
      cur.out += +e.quantity_out || 0;
      monthMap.set(m, cur);
    });
    const months = Array.from(monthMap.keys());
    this.monthlyChartData.set({
      labels: months,
      datasets: [
        { label: this.translate.instant('INVENTORY.QTY_IN'), data: months.map(m => monthMap.get(m)!.in), backgroundColor: '#10b981' },
        { label: this.translate.instant('INVENTORY.QTY_OUT'), data: months.map(m => monthMap.get(m)!.out), backgroundColor: '#ef4444' },
      ]
    });

    // 3. Movement types (doughnut)
    const typeMap = new Map<string, number>();
    ents.forEach(e => {
      const t = e.movement_type_label || e.movement_type;
      typeMap.set(t, (typeMap.get(t) || 0) + 1);
    });
    const typeColors: Record<string, string> = {
      receipt: '#10b981', issue: '#ef4444', transfer_in: '#3b82f6', transfer_out: '#f59e0b',
      opening: '#8b5cf6', adjustment: '#ec4899'
    };
    const typeKeys = Array.from(typeMap.keys());
    this.movementChartData.set({
      labels: typeKeys,
      datasets: [{
        data: typeKeys.map(k => typeMap.get(k)!),
        backgroundColor: typeKeys.map((k, i) => {
          const lower = k.toLowerCase();
          for (const [key, color] of Object.entries(typeColors)) {
            if (lower.includes(key)) return color;
          }
          return ['#6366f1', '#14b8a6', '#f97316', '#a855f7', '#ec4899'][i % 5];
        }),
      }]
    });

    // 4. Qty by warehouse (horizontal bar)
    const bals = this.balances();
    if (bals.length > 0) {
      this.warehouseChartData.set({
        labels: bals.map(b => b.warehouse_name),
        datasets: [{
          label: this.translate.instant('INVENTORY.QUANTITY'),
          data: bals.map(b => +b.quantity),
          backgroundColor: '#6366f1',
          borderRadius: 6,
        }]
      });
    }
  }

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

  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';
  }

  private showError(err: any): void {
    const detail = err.error?.message || 'Failed';
    this.messageService.add({ severity: 'error', summary: this.translate.instant('COMMON.ERROR'), detail });
  }
}
