import { Injectable } from '@angular/core';
import { firstValueFrom } from 'rxjs';
import { ResumoService, PlanoContratoResumo, MacrophonyPlan } from './resumo.service';

export type PlanSuggestion = {
  franquiaGb?: number | null;
  valorPlano?: number | null;
};

@Injectable({ providedIn: 'root' })
export class PlanAutoFillService {
  private loaded = false;
  private loadingPromise: Promise<void> | null = null;
  private planMap = new Map<string, PlanSuggestion>();
  private planOptions: string[] = [];

  constructor(private resumoService: ResumoService) {}

  async load(): Promise<void> {
    if (this.loaded) return;
    if (this.loadingPromise) return this.loadingPromise;

    this.loadingPromise = firstValueFrom(this.resumoService.getResumo())
      .then((res) => {
        const items: Array<PlanoContratoResumo | MacrophonyPlan> = [
          ...(res?.planoContratoResumos ?? []),
          ...(res?.macrophonyPlans ?? [])
        ];

        items.forEach((row) => this.addPlanRule(row));
        this.planOptions = Array.from(new Set(this.planOptions)).sort((a, b) =>
          a.localeCompare(b, 'pt-BR', { sensitivity: 'base' })
        );

        this.loaded = true;
      })
      .catch(() => {
        this.loaded = true;
      })
      .finally(() => {
        this.loadingPromise = null;
      });

    return this.loadingPromise;
  }

  getPlanOptions(): string[] {
    return [...this.planOptions];
  }

  suggest(planName: string | null | undefined): PlanSuggestion | null {
    const plan = (planName ?? '').trim();
    if (!plan) return null;

    const key = this.normalizePlan(plan);
    const fromMap = this.planMap.get(key);

    const franquia = fromMap?.franquiaGb ?? this.parseFranquiaFromPlan(plan);
    const valorPlano = fromMap?.valorPlano ?? null;

    if (franquia == null && valorPlano == null) return null;
    return { franquiaGb: franquia ?? null, valorPlano };
  }

  private addPlanRule(row: PlanoContratoResumo | MacrophonyPlan) {
    const plano = (row?.planoContrato ?? '').toString().trim();
    if (!plano) return;

    const key = this.normalizePlan(plano);
    const current = this.planMap.get(key) || {};

    const franquia = this.toNumber((row as any).franquiaGb ?? (row as any).gb);
    const valorPlano = this.toNumber((row as any).valorIndividualComSvas);

    const next: PlanSuggestion = {
      franquiaGb: current.franquiaGb ?? franquia ?? null,
      valorPlano: current.valorPlano ?? valorPlano ?? null
    };

    this.planMap.set(key, next);
    this.planOptions.push(plano);
  }

  private normalizePlan(plan: string): string {
    return plan.trim().replace(/\s+/g, ' ').toUpperCase();
  }

  private toNumber(value: any): number | null {
    if (value === null || value === undefined || value === '') return null;
    if (typeof value === 'number') return Number.isFinite(value) ? value : null;

    const raw = String(value).trim();
    if (!raw) return null;

    const cleaned = raw.replace(/[^0-9,.-]/g, '').replace(',', '.');
    const n = parseFloat(cleaned);
    return Number.isFinite(n) ? n : null;
  }

  private parseFranquiaFromPlan(plan: string): number | null {
    const match = plan.match(/(\d+(?:[.,]\d+)?)\s*(GB|MB)/i);
    if (!match) return null;

    const raw = match[1].replace(',', '.');
    const unit = match[2].toUpperCase();

    const value = parseFloat(raw);
    if (!Number.isFinite(value)) return null;

    if (unit === 'MB') {
      return Number((value / 1000).toFixed(4));
    }

    return value;
  }
}
