import { Component, OnDestroy, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { HttpErrorResponse } from '@angular/common/http';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';
import { VigenciaService, VigenciaRow, VigenciaClientGroup, PagedResult, UpdateVigenciaRequest } from '../../services/vigencia.service';
import { CustomSelectComponent } from '../../components/custom-select/custom-select';
import { AuthService } from '../../services/auth.service';
import { LinesService, MobileLineDetail } from '../../services/lines.service';
import { PlanAutoFillService } from '../../services/plan-autofill.service';
import { confirmDeletionWithTyping } from '../../utils/destructive-confirmation';

type SortDir = 'asc' | 'desc';
type ToastType = 'success' | 'danger';
type ViewMode = 'lines' | 'groups';

interface LineOptionDto {
  id: string;
  item: number;
  linha: string | null;
  usuario: string | null;
  label?: string;
}

@Component({
  selector: 'app-vigencia',
  standalone: true,
  imports: [CommonModule, FormsModule, CustomSelectComponent],
  templateUrl: './vigencia.html',
  styleUrls: ['./vigencia.scss'],
})
export class VigenciaComponent implements OnInit, OnDestroy {
  loading = false;
  errorMsg = '';

  // Filtros
  search = '';
  client = '';
  clients: string[] = [];

  // Paginação
  page = 1;
  pageSize = 10;
  pageSizeOptions = [10, 20, 50, 100];
  total = 0;

  // Ordenação
  sortBy = 'cliente';
  sortDir: SortDir = 'asc';

  // PADRÃO: GROUPS
  viewMode: ViewMode = 'groups';

  // Dados
  groups: VigenciaClientGroup[] = []; 
  rows: VigenciaRow[] = []; 

  // === KPIs GERAIS (Vindos do Backend) ===
  kpiTotalClientes = 0;
  kpiTotalLinhas = 0;
  kpiTotalVencidos = 0;

  // === ACORDEÃO ===
  expandedGroup: string | null = null;
  expandedLoading = false;
  groupRows: VigenciaRow[] = []; 

  // UI
  detailsOpen = false;
  selectedRow: VigenciaRow | null = null;
  editOpen = false;
  editSaving = false;
  editModel: VigenciaRow | null = null;
  editEfetivacao = '';
  editTermino = '';
  editingId: string | null = null;
  deleteOpen = false;
  deleteTarget: VigenciaRow | null = null;

  createOpen = false;
  createSaving = false;
  createModel: any = {
    selectedClient: '',
    mobileLineId: '',
    item: '',
    conta: '',
    linha: '',
    cliente: '',
    usuario: '',
    planoContrato: '',
    total: null
  };
  createEfetivacao = '';
  createTermino = '';

  lineOptionsCreate: LineOptionDto[] = [];
  createClientsLoading = false;
  createLinesLoading = false;
  clientsFromGeral: string[] = [];
  planOptions: string[] = [];

  isSysAdmin = false;
  toastOpen = false;
  toastMessage = '';
  toastType: ToastType = 'success';
  private toastTimer: any = null;
  private searchTimer: any = null;
  private readonly subs = new Subscription();

  constructor(
    private vigenciaService: VigenciaService,
    private authService: AuthService,
    private linesService: LinesService,
    private planAutoFill: PlanAutoFillService,
    private route: ActivatedRoute
  ) {}

  ngOnInit(): void {
    this.isSysAdmin = this.authService.hasRole('sysadmin');
    this.loadClients();
    this.loadPlanRules();
    this.fetch(1);
    this.bindOpenFromNotificationQuery();
  }

  ngOnDestroy(): void {
    if (this.searchTimer) clearTimeout(this.searchTimer);
    if (this.toastTimer) clearTimeout(this.toastTimer);
    this.subs.unsubscribe();
  }

  setView(mode: ViewMode): void {
    if (this.viewMode === mode) return;
    this.viewMode = mode;
    this.page = 1;
    this.expandedGroup = null;
    this.groupRows = [];
    this.sortBy = mode === 'groups' ? 'cliente' : 'item';
    this.fetch(1);
  }

  loadClients(): void {
    this.vigenciaService.getClients().subscribe({
      next: (list) => (this.clients = list ?? []),
      error: () => (this.clients = []),
    });
  }

  private async loadPlanRules() {
    try {
      await this.planAutoFill.load();
      this.planOptions = this.planAutoFill.getPlanOptions();
    } catch {
      this.planOptions = [];
    }
  }

  get totalPages(): number {
    return Math.max(1, Math.ceil((this.total || 0) / (this.pageSize || 10)));
  }

  fetch(goToPage?: number): void {
    if (goToPage) this.page = goToPage;
    this.loading = true;
    this.errorMsg = '';
    
    if(goToPage && goToPage !== this.page) this.expandedGroup = null;

    if (this.viewMode === 'groups') {
      this.fetchGroups();
    } else {
      this.fetchLines();
    }
  }

  private fetchGroups() {
    this.vigenciaService.getGroups({
      search: this.search?.trim(),
      page: this.page,
      pageSize: this.pageSize,
      sortBy: this.sortBy,
      sortDir: this.sortDir,
    }).subscribe({
      next: (res) => {
        // ✅ Preenche Lista
        this.groups = res.data.items || [];
        this.total = res.data.total || 0;

        // ✅ Preenche KPIs Globais
        this.kpiTotalClientes = res.kpis.totalClientes;
        this.kpiTotalLinhas = res.kpis.totalLinhas;
        this.kpiTotalVencidos = res.kpis.totalVencidos;

        this.loading = false;
      },
      error: (err) => this.handleError(err, 'Erro ao carregar clientes.'),
    });
  }

  private fetchLines() {
    this.vigenciaService.getVigencia({
      search: this.search?.trim(),
      client: this.client?.trim(),
      page: this.page,
      pageSize: this.pageSize,
      sortBy: this.sortBy,
      sortDir: this.sortDir,
    }).subscribe({
      next: (res) => {
        this.rows = res.items || [];
        this.total = res.total || 0;
        this.loading = false;
      },
      error: (err) => this.handleError(err, 'Erro ao carregar linhas.'),
    });
  }

  toggleGroup(g: VigenciaClientGroup): void {
    if (this.expandedGroup === g.cliente) {
      this.expandedGroup = null; 
      this.groupRows = [];
      return;
    }

    this.expandedGroup = g.cliente;
    this.expandedLoading = true;
    this.groupRows = []; 

    this.vigenciaService.getVigencia({
      client: g.cliente, 
      page: 1,
      pageSize: 200, 
      sortBy: 'item',
      sortDir: 'asc'
    }).subscribe({
      next: (res) => {
        this.groupRows = res.items || [];
        this.expandedLoading = false;
      },
      error: () => {
        this.showToast('Erro ao carregar detalhes do cliente.', 'danger');
        this.expandedLoading = false;
      }
    });
  }

  public isVencido(dateValue: any): boolean {
    if(!dateValue) return false;
    const d = this.parseAnyDate(dateValue);
    if(!d) return false;
    return this.startOfDay(d) < this.startOfDay(new Date());
  }

  public isAtivo(dateValue: any): boolean {
    if(!dateValue) return true; 
    const d = this.parseAnyDate(dateValue);
    if(!d) return true;
    return this.startOfDay(d) >= this.startOfDay(new Date());
  }

  public isAVencer(dateValue: any): boolean {
    if (!dateValue) return false;
    const d = this.parseAnyDate(dateValue);
    if (!d) return false;
    const today = this.startOfDay(new Date());
    const end = this.startOfDay(d);
    const days = Math.round((end.getTime() - today.getTime()) / (24 * 60 * 60 * 1000));
    return days >= 0 && days <= 30;
  }

  getRenewalBadge(row: VigenciaRow): string {
    if (!row.autoRenewYears) return '';
    return `Auto +${row.autoRenewYears} ano(s)`;
  }

  public parseAnyDate(value: any): Date | null {
    if (!value) return null;
    const d = new Date(value);
    return isNaN(d.getTime()) ? null : d;
  }

  public startOfDay(d: Date): Date { 
    return new Date(d.getFullYear(), d.getMonth(), d.getDate()); 
  }

  onSearchChange() {
    if (this.searchTimer) clearTimeout(this.searchTimer);
    this.searchTimer = setTimeout(() => this.fetch(1), 300);
  }

  clearFilters() {
    this.search = '';
    if (this.searchTimer) clearTimeout(this.searchTimer);
    this.fetch(1);
  }

  scheduleAutoRenew(row: VigenciaRow): void {
    if (!row?.id) return;
    const years = 2;

    this.vigenciaService.configureAutoRenew(row.id, { years }).subscribe({
      next: () => {
        row.autoRenewYears = years;
        row.autoRenewReferenceEndDate = row.dtTerminoFidelizacao;
        row.autoRenewConfiguredAt = new Date().toISOString();
        this.showToast(`Renovação automática (+${years} ano${years > 1 ? 's' : ''}) programada.`, 'success');
      },
      error: () => this.showToast('Não foi possível programar a renovação automática.', 'danger')
    });
  }

  openDetails(r: VigenciaRow) { this.selectedRow = r; this.detailsOpen = true; }
  closeDetails() { this.detailsOpen = false; }

  openEdit(r: VigenciaRow) {
    if (!this.isSysAdmin) return;
    this.editingId = r.id;
    this.editModel = { ...r };
    this.editEfetivacao = this.toDateInput(r.dtEfetivacaoServico);
    this.editTermino = this.toDateInput(r.dtTerminoFidelizacao);
    this.editOpen = true;
  }

  closeEdit() {
    this.editOpen = false;
    this.editSaving = false;
    this.editModel = null;
    this.editEfetivacao = '';
    this.editTermino = '';
    this.editingId = null;
  }

  saveEdit() {
    if (!this.editModel || !this.editingId) return;
    this.editSaving = true;

    const payload: UpdateVigenciaRequest = {
      item: this.toNullableNumber(this.editModel.item),
      conta: this.editModel.conta,
      linha: this.editModel.linha,
      cliente: this.editModel.cliente,
      usuario: this.editModel.usuario,
      planoContrato: this.editModel.planoContrato,
      dtEfetivacaoServico: this.dateInputToIso(this.editEfetivacao),
      dtTerminoFidelizacao: this.dateInputToIso(this.editTermino),
      total: this.toNullableNumber(this.editModel.total)
    };

    this.vigenciaService.update(this.editingId, payload).subscribe({
      next: () => {
        this.editSaving = false;
        this.closeEdit();
        this.fetch();
        this.showToast('Registro atualizado!', 'success');
      },
      error: () => {
        this.editSaving = false;
        this.showToast('Erro ao salvar.', 'danger');
      }
    });
  }

  // ==========================
  // CREATE
  // ==========================
  openCreate() {
    if (!this.isSysAdmin) return;
    this.resetCreateModel();
    this.createOpen = true;
    this.preloadGeralClients();
  }

  closeCreate() {
    this.createOpen = false;
    this.createSaving = false;
    this.createModel = null;
  }

  private resetCreateModel() {
    this.createModel = {
      selectedClient: '',
      mobileLineId: '',
      item: '',
      conta: '',
      linha: '',
      cliente: '',
      usuario: '',
      planoContrato: '',
      total: null
    };
    this.createEfetivacao = '';
    this.createTermino = '';
    this.lineOptionsCreate = [];
    this.createLinesLoading = false;
    this.createClientsLoading = false;
  }

  private preloadGeralClients() {
    this.createClientsLoading = true;
    this.linesService.getClients().subscribe({
      next: (list) => {
        this.clientsFromGeral = list ?? [];
        this.createClientsLoading = false;
      },
      error: () => {
        this.clientsFromGeral = [];
        this.createClientsLoading = false;
      }
    });
  }

  onCreateClientChange() {
    const c = (this.createModel.selectedClient ?? '').trim();
    this.createModel.mobileLineId = '';
    this.createModel.linha = '';
    this.createModel.conta = '';
    this.createModel.usuario = '';
    this.createModel.planoContrato = '';
    this.createModel.total = null;
    this.createModel.cliente = c;
    this.lineOptionsCreate = [];

    if (c) this.loadLinesForClient(c);
  }

  private loadLinesForClient(cliente: string) {
    const c = (cliente ?? '').trim();
    if (!c) return;

    this.createLinesLoading = true;
    this.linesService.getLinesByClient(c).subscribe({
      next: (items: any[]) => {
        const mapped: LineOptionDto[] = (items ?? [])
          .filter(x => !!String(x?.id ?? '').trim())
          .map(x => ({
            id: String(x.id),
            item: Number(x.item ?? 0),
            linha: x.linha ?? null,
            usuario: x.usuario ?? null,
            label: `${x.item ?? ''} • ${x.linha ?? '-'} • ${x.usuario ?? 'SEM USUÁRIO'}`
          }))
          .filter(x => !!String(x.linha ?? '').trim());

        this.lineOptionsCreate = mapped;
        this.createLinesLoading = false;
      },
      error: () => {
        this.lineOptionsCreate = [];
        this.createLinesLoading = false;
        this.showToast('Erro ao carregar linhas da GERAL.', 'danger');
      }
    });
  }

  onCreateLineChange() {
    const id = String(this.createModel.mobileLineId ?? '').trim();
    if (!id) return;

    this.linesService.getById(id).subscribe({
      next: (d: MobileLineDetail) => this.applyLineDetailToCreate(d),
      error: () => this.showToast('Erro ao carregar dados da linha.', 'danger')
    });
  }

  private applyLineDetailToCreate(d: MobileLineDetail) {
    this.createModel.linha = d.linha ?? '';
    this.createModel.conta = d.conta ?? '';
    this.createModel.cliente = d.cliente ?? this.createModel.cliente ?? '';
    this.createModel.usuario = d.usuario ?? '';
    this.createModel.planoContrato = d.planoContrato ?? '';
    this.createEfetivacao = this.toDateInput(d.dtEfetivacaoServico ?? null);
    this.createTermino = this.toDateInput(d.dtTerminoFidelizacao ?? null);

    this.ensurePlanOption(this.createModel.planoContrato);

    if (!String(this.createModel.item ?? '').trim() && d.item) {
      this.createModel.item = String(d.item);
    }

    this.onCreatePlanChange();
  }

  onCreatePlanChange() {
    this.ensurePlanOption(this.createModel?.planoContrato);
    this.applyPlanSuggestion(this.createModel);
  }

  onEditPlanChange() {
    if (!this.editModel) return;
    this.ensurePlanOption(this.editModel?.planoContrato);
    this.applyPlanSuggestion(this.editModel);
  }

  private applyPlanSuggestion(model: any) {
    const plan = (model?.planoContrato ?? '').toString().trim();
    if (!plan) return;

    const suggestion = this.planAutoFill.suggest(plan);
    if (!suggestion) return;

    if (suggestion.valorPlano != null) {
      model.total = suggestion.valorPlano;
    }
  }

  private ensurePlanOption(plan: any) {
    const p = (plan ?? '').toString().trim();
    if (!p) return;
    if (!this.planOptions.includes(p)) {
      this.planOptions = [p, ...this.planOptions];
    }
  }

  saveCreate() {
    if (!this.createModel) return;
    this.applyPlanSuggestion(this.createModel);

    const payload = {
      item: this.toNullableNumber(this.createModel.item),
      conta: this.createModel.conta,
      linha: this.createModel.linha,
      cliente: this.createModel.cliente,
      usuario: this.createModel.usuario,
      planoContrato: this.createModel.planoContrato,
      dtEfetivacaoServico: this.dateInputToIso(this.createEfetivacao),
      dtTerminoFidelizacao: this.dateInputToIso(this.createTermino),
      total: this.toNullableNumber(this.createModel.total)
    };

    this.createSaving = true;
    this.vigenciaService.create(payload).subscribe({
      next: () => {
        this.createSaving = false;
        this.closeCreate();
        this.fetch();
        this.showToast('Vigência criada com sucesso!', 'success');
      },
      error: () => {
        this.createSaving = false;
        this.showToast('Erro ao criar vigência.', 'danger');
      }
    });
  }

  openDelete(r: VigenciaRow) {
    if (!this.isSysAdmin) return;
    this.deleteTarget = r;
    this.deleteOpen = true;
  }

  cancelDelete() {
    this.deleteOpen = false;
    this.deleteTarget = null;
  }

  async confirmDelete() {
    if (!this.deleteTarget) return;
    if (!(await confirmDeletionWithTyping('este registro de vigência'))) return;
    const id = this.deleteTarget.id;
    this.vigenciaService.remove(id).subscribe({
      next: () => {
        this.deleteOpen = false;
        this.deleteTarget = null;
        this.fetch();
        this.showToast('Registro removido.', 'success');
      },
      error: () => {
        this.deleteOpen = false;
        this.deleteTarget = null;
        this.showToast('Erro ao remover.', 'danger');
      }
    });
  }

  private toDateInput(value: string | null): string {
    if (!value) return '';
    const d = new Date(value);
    if (isNaN(d.getTime())) return '';
    return d.toISOString().slice(0, 10);
  }

  private dateInputToIso(value: string): string | null {
    if (!value) return null;
    const d = new Date(`${value}T00:00:00`);
    if (isNaN(d.getTime())) return null;
    return d.toISOString();
  }

  private toNullableNumber(value: any): number | null {
    if (value === undefined || value === null || value === '') return null;
    const n = Number(value);
    return Number.isNaN(n) ? null : n;
  }

  private bindOpenFromNotificationQuery(): void {
    this.subs.add(
      this.route.queryParamMap.subscribe((params) => {
        const lineId = (params.get('lineId') ?? '').trim();
        const linha = (params.get('linha') ?? '').trim();
        if (!lineId && !linha) return;

        const openMode = (params.get('open') ?? 'edit').trim().toLowerCase();
        if (lineId) {
          this.openVigenciaLineById(lineId, openMode);
        } else if (linha) {
          this.openVigenciaLineByNumber(linha, openMode);
        }
      })
    );
  }

  private openVigenciaLineById(lineId: string, openMode: string): void {
    this.vigenciaService.getById(lineId).subscribe({
      next: (row) => {
        if (this.isSysAdmin && openMode !== 'details') {
          this.openEdit(row);
          return;
        }
        this.openDetails(row);
      },
      error: () => this.showToast('Não foi possível abrir a linha da vigência pela notificação.', 'danger')
    });
  }

  private openVigenciaLineByNumber(linha: string, openMode: string): void {
    const onlyDigits = (linha || '').replace(/\D/g, '');
    const lookup = onlyDigits || linha;
    if (!lookup) return;

    this.vigenciaService.getVigencia({
      search: lookup,
      page: 1,
      pageSize: 20,
      sortBy: 'item',
      sortDir: 'asc'
    }).subscribe({
      next: (res) => {
        const rows = res?.items ?? [];
        const match = rows.find(r => (r.linha ?? '').replace(/\D/g, '') === onlyDigits) ?? rows[0];
        if (!match) {
          this.showToast('Linha da notificação não encontrada na vigência.', 'danger');
          return;
        }

        if (this.isSysAdmin && openMode !== 'details') {
          this.openEdit(match);
          return;
        }
        this.openDetails(match);
      },
      error: () => this.showToast('Não foi possível localizar a linha da notificação na vigência.', 'danger')
    });
  }

  handleError(err: HttpErrorResponse, msg: string) {
    this.loading = false;
    this.expandedLoading = false;
    this.errorMsg = (err.error as any)?.message || msg;
    this.showToast(msg, 'danger');
  }

  showToast(msg: string, type: ToastType) {
    this.toastMessage = msg; this.toastType = type; this.toastOpen = true;
    if(this.toastTimer) clearTimeout(this.toastTimer);
    this.toastTimer = setTimeout(() => this.toastOpen = false, 3000);
  }
  hideToast() { this.toastOpen = false; }
}
