import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { HttpErrorResponse } from '@angular/common/http';
import { CustomSelectComponent } from '../../components/custom-select/custom-select';

import { 
  DadosUsuariosService, 
  UserDataClientGroup, 
  UserDataRow,
  UserDataGroupResponse,
  PagedResult,
  UpdateUserDataRequest,
  CreateUserDataRequest
} from '../../services/dados-usuarios.service'; 
import { AuthService } from '../../services/auth.service';
import { LinesService, MobileLineDetail } from '../../services/lines.service';
import { confirmDeletionWithTyping } from '../../utils/destructive-confirmation';

type ViewMode = 'lines' | 'groups';

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

interface SimpleOption {
  label: string;
  value: string;
}

@Component({
  selector: 'app-dados-usuarios',
  standalone: true,
  imports: [CommonModule, FormsModule, CustomSelectComponent],
  templateUrl: './dados-usuarios.html',
  styleUrls: ['./dados-usuarios.scss']
})
export class DadosUsuarios implements OnInit {
  
  @ViewChild('successToast', { static: false }) successToast!: ElementRef;

  loading = false;
  errorMsg = '';

  // Filtros
  search = '';
  tipoFilter: 'PF' | 'PJ' = 'PF';
  
  // Paginação
  page = 1;
  pageSize = 10;
  pageSizeOptions = [10, 20, 50, 100];
  total = 0;

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

  // PADRÃO: GROUPS (Acordeão)
  viewMode: ViewMode = 'groups';

  // Dados
  groups: UserDataClientGroup[] = []; 
  rows: UserDataRow[] = []; 

  // KPIs
  kpiTotalRegistros = 0;
  kpiClientesUnicos = 0;
  kpiComCpf = 0;
  kpiComCnpj = 0;
  kpiComEmail = 0;

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

  // Modal / Toast
  detailsOpen = false;
  selectedRow: UserDataRow | null = null;
  editOpen = false;
  editSaving = false;
  editModel: UserDataRow | null = null;
  editDateNascimento = '';
  editingId: string | null = null;
  deleteOpen = false;
  deleteTarget: UserDataRow | null = null;

  createOpen = false;
  createSaving = false;
  createModel: any = null;
  createDateNascimento = '';
  createFranquiaLineTotal = 0;
  editFranquiaLineTotal = 0;
  editSelectedLineId = '';
  editLineOptions: LineOptionDto[] = [];
  lineOptionsCreate: LineOptionDto[] = [];
  readonly tipoPessoaOptions: SimpleOption[] = [
    { label: 'Pessoa Física', value: 'PF' },
    { label: 'Pessoa Jurídica', value: 'PJ' },
  ];
  createLinesLoading = false;

  isSysAdmin = false;
  toastOpen = false;
  toastMessage = '';
  toastType: 'success' | 'danger' = 'success';
  private toastTimer: any = null;
  private searchTimer: any = null;

  constructor(
    private service: DadosUsuariosService,
    private authService: AuthService,
    private linesService: LinesService
  ) {}

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

  // Alternar Visualização
  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);
  }

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

  get pageStart(): number { return (this.page - 1) * this.pageSize + 1; }
  
  get pageEnd(): number { 
    const end = this.page * this.pageSize;
    return end > this.total ? this.total : end; 
  }

  get pageNumbers(): number[] {
    const total = this.totalPages;
    const current = this.page;
    const max = 5;
    let start = Math.max(1, current - 2);
    let end = Math.min(total, start + (max - 1));
    start = Math.max(1, end - (max - 1));
    const pages: number[] = [];
    for (let i = start; i <= end; i++) pages.push(i);
    return pages;
  }

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

    if (this.viewMode === 'groups') {
      this.fetchGroups();
    } else {
      this.fetchLines(); // Fallback se quiser usar
    }
  }

  refresh() {
      this.fetch(1);
  }

  private fetchGroups() {
    this.service.getGroups({
      search: this.search?.trim(),
      tipo: this.tipoFilter,
      page: this.page,
      pageSize: this.pageSize,
      sortBy: this.sortBy,
      sortDir: this.sortDir,
    }).subscribe({
      next: (res: UserDataGroupResponse) => {
        this.groups = res.data.items || [];
        this.total = res.data.total || 0;
        
        this.kpiTotalRegistros = res.kpis.totalRegistros;
        this.kpiClientesUnicos = res.kpis.clientesUnicos;
        this.kpiComCpf = res.kpis.comCpf;
        this.kpiComCnpj = res.kpis.comCnpj;
        this.kpiComEmail = res.kpis.comEmail;

        this.loading = false;
      },
      error: (err: HttpErrorResponse) => {
        this.loading = false;
        this.showToast('Erro ao carregar dados.', 'danger');
      }
    });
  }

  private fetchLines() {
      // Implementação opcional para modo lista plana
  }

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

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

    this.service.getRows({
      client: g.cliente, 
      tipo: this.tipoFilter,
      page: 1,
      pageSize: 200, 
      sortBy: 'item',
      sortDir: 'asc'
    }).subscribe({
      next: (res: PagedResult<UserDataRow>) => {
        this.groupRows = res.items || [];
        this.expandedLoading = false;
      },
      error: (err: HttpErrorResponse) => {
        this.showToast('Erro ao carregar usuários do cliente.', 'danger');
        this.expandedLoading = false;
      }
    });
  }

  onSearch() {
    if (this.searchTimer) clearTimeout(this.searchTimer);
    this.searchTimer = setTimeout(() => {
      this.page = 1;
      this.expandedGroup = null;
      this.fetch();
    }, 400);
  }

  setTipoFilter(tipo: 'PF' | 'PJ') {
    if (this.tipoFilter === tipo) return;
    this.tipoFilter = tipo;
    this.page = 1;
    this.expandedGroup = null;
    this.groupRows = [];
    this.fetch();
  }

  clearFilters() { this.search = ''; this.fetch(1); }
  
  onPageSizeChange() {
    this.page = 1;
    this.fetch();
  }

  goToPage(p: number) {
    this.page = p;
    this.fetch();
  }

  openDetails(row: UserDataRow) {
      this.service.getById(row.id).subscribe({
        next: (fullData: UserDataRow) => {
          const tipo = this.normalizeTipo(fullData);
          this.selectedRow = {
            ...fullData,
            tipoPessoa: tipo,
            nome: fullData.nome || (tipo === 'PF' ? fullData.cliente : ''),
            razaoSocial: fullData.razaoSocial || (tipo === 'PJ' ? fullData.cliente : '')
          };
          this.detailsOpen = true;
        },
        error: (err: HttpErrorResponse) => this.showToast('Erro ao abrir detalhes', 'danger')
      });
  }
  
  closeDetails() { this.detailsOpen = false; }

  openEdit(row: UserDataRow) {
    if (!this.isSysAdmin) return;
    this.service.getById(row.id).subscribe({
      next: (fullData: UserDataRow) => {
        this.editingId = fullData.id;
        const tipo = this.normalizeTipo(fullData);
        this.editModel = {
          ...fullData,
          tipoPessoa: tipo,
          nome: fullData.nome || (tipo === 'PF' ? fullData.cliente : ''),
          razaoSocial: fullData.razaoSocial || (tipo === 'PJ' ? fullData.cliente : '')
        };
        this.editDateNascimento = this.toDateInput(fullData.dataNascimento);
        this.editFranquiaLineTotal = 0;
        this.editSelectedLineId = '';
        this.editLineOptions = [];
        this.editOpen = true;
        this.loadReserveLinesForSelects();
      },
      error: () => this.showToast('Erro ao abrir edição', 'danger')
    });
  }

  closeEdit() {
    this.editOpen = false;
    this.editSaving = false;
    this.editModel = null;
    this.editDateNascimento = '';
    this.editingId = null;
    this.editSelectedLineId = '';
    this.editLineOptions = [];
    this.editFranquiaLineTotal = 0;
  }

  onEditTipoChange() {
    if (!this.editModel) return;
    const tipo = (this.editModel.tipoPessoa ?? 'PF').toString().toUpperCase();
    this.editModel.tipoPessoa = tipo;
    if (tipo === 'PJ') {
      this.editModel.cpf = '';
      if (!this.editModel.razaoSocial) this.editModel.razaoSocial = this.editModel.cliente;
    } else {
      this.editModel.cnpj = '';
      if (!this.editModel.nome) this.editModel.nome = this.editModel.cliente;
    }
  }

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

    const tipo = (this.editModel.tipoPessoa ?? this.tipoFilter).toString().toUpperCase();
    const cliente = tipo === 'PJ'
      ? (this.editModel.razaoSocial || this.editModel.cliente)
      : (this.editModel.nome || this.editModel.cliente);

    const payload: UpdateUserDataRequest = {
      item: this.toNullableNumber(this.editModel.item),
      linha: this.editModel.linha,
      cliente,
      tipoPessoa: tipo,
      nome: this.editModel.nome,
      razaoSocial: this.editModel.razaoSocial,
      cnpj: this.editModel.cnpj,
      cpf: this.editModel.cpf,
      rg: this.editModel.rg,
      email: this.editModel.email,
      endereco: this.editModel.endereco,
      celular: this.editModel.celular,
      telefoneFixo: this.editModel.telefoneFixo,
      dataNascimento: this.dateInputToIso(this.editDateNascimento)
    };

    this.service.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 alterações.', 'danger');
      }
    });
  }

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

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

  private resetCreateModel() {
    this.createModel = {
      selectedClient: '',
      mobileLineId: '',
      item: '',
      linha: '',
      cliente: '',
      tipoPessoa: this.tipoFilter,
      nome: '',
      razaoSocial: '',
      cnpj: '',
      cpf: '',
      rg: '',
      email: '',
      endereco: '',
      celular: '',
      telefoneFixo: ''
    };
    this.createDateNascimento = '';
    this.createFranquiaLineTotal = 0;
    this.lineOptionsCreate = [];
    this.createLinesLoading = false;
  }

  onCreateTipoChange() {
    const tipo = (this.createModel?.tipoPessoa ?? 'PF').toString().toUpperCase();
    this.createModel.tipoPessoa = tipo;
    if (tipo === 'PJ') {
      this.createModel.cpf = '';
      if (!this.createModel.razaoSocial) this.createModel.razaoSocial = this.createModel.cliente;
    } else {
      this.createModel.cnpj = '';
      if (!this.createModel.nome) this.createModel.nome = this.createModel.cliente;
    }
  }

  private loadReserveLinesForSelects(onDone?: () => void) {
    this.createLinesLoading = true;
    this.linesService.getLinesByClient('RESERVA').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;
        if (this.editModel) this.syncEditLineOptions();
        this.createLinesLoading = false;
        onDone?.();
      },
      error: () => {
        this.lineOptionsCreate = [];
        this.editLineOptions = [];
        this.createLinesLoading = false;
        this.showToast('Erro ao carregar linhas da Reserva.', 'danger');
        onDone?.();
      }
    });
  }

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

  onEditLineChange() {
    const id = String(this.editSelectedLineId ?? '').trim();
    if (!id || id === '__CURRENT__') return;
    this.linesService.getById(id).subscribe({
      next: (d: MobileLineDetail) => this.applyLineDetailToEdit(d),
      error: () => this.showToast('Erro ao carregar dados da linha.', 'danger')
    });
  }

  private syncEditLineOptions() {
    if (!this.editModel) {
      this.editLineOptions = [];
      this.editSelectedLineId = '';
      return;
    }

    const currentLine = String(this.editModel.linha ?? '').trim();
    const fromReserva = this.lineOptionsCreate.find((x) => String(x.linha ?? '').trim() === currentLine);
    const options = [...this.lineOptionsCreate];

    if (currentLine && !fromReserva) {
      options.unshift({
        id: '__CURRENT__',
        item: Number(this.editModel.item ?? 0),
        linha: currentLine,
        usuario: this.editModel.cliente ?? null,
        label: `Atual • ${currentLine}`
      });
    }

    this.editLineOptions = options;
    this.editSelectedLineId = fromReserva?.id ?? (currentLine ? '__CURRENT__' : '');
    if (fromReserva?.id) {
      this.onEditLineChange();
    }
  }

  private applyLineDetailToCreate(d: MobileLineDetail) {
    this.createModel.linha = d.linha ?? '';
    this.createFranquiaLineTotal = this.toNullableNumber(d.franquiaLine) ?? 0;
    if (!String(this.createModel.item ?? '').trim() && d.item) {
      this.createModel.item = String(d.item);
    }

    const lineClient = String(d.cliente ?? '').trim();
    const isReserva = lineClient.localeCompare('RESERVA', 'pt-BR', { sensitivity: 'base' }) === 0;
    if (!isReserva && lineClient) {
      this.createModel.cliente = lineClient;
    }

    if ((this.createModel.tipoPessoa ?? '').toUpperCase() === 'PJ') {
      if (!this.createModel.razaoSocial) this.createModel.razaoSocial = this.createModel.cliente;
    } else {
      if (!this.createModel.nome) this.createModel.nome = this.createModel.cliente;
    }
  }

  private applyLineDetailToEdit(d: MobileLineDetail) {
    if (!this.editModel) return;
    this.editModel.linha = d.linha ?? this.editModel.linha;
    this.editFranquiaLineTotal = this.toNullableNumber(d.franquiaLine) ?? 0;
    if (!String(this.editModel.item ?? '').trim() && d.item) {
      this.editModel.item = d.item;
    }
  }

  saveCreate() {
    if (!this.createModel) return;
    this.createSaving = true;

    const tipo = (this.createModel.tipoPessoa ?? this.tipoFilter).toString().toUpperCase();
    const cliente = tipo === 'PJ'
      ? (this.createModel.razaoSocial || this.createModel.cliente)
      : (this.createModel.nome || this.createModel.cliente);

    const payload: CreateUserDataRequest = {
      item: this.toNullableNumber(this.createModel.item),
      linha: this.createModel.linha,
      cliente,
      tipoPessoa: tipo,
      nome: this.createModel.nome,
      razaoSocial: this.createModel.razaoSocial,
      cnpj: this.createModel.cnpj,
      cpf: this.createModel.cpf,
      rg: this.createModel.rg,
      email: this.createModel.email,
      endereco: this.createModel.endereco,
      celular: this.createModel.celular,
      telefoneFixo: this.createModel.telefoneFixo,
      dataNascimento: this.dateInputToIso(this.createDateNascimento)
    };

    this.service.create(payload).subscribe({
      next: () => {
        this.createSaving = false;
        this.closeCreate();
        this.fetch();
        this.showToast('Usuário criado com sucesso!', 'success');
      },
      error: () => {
        this.createSaving = false;
        this.showToast('Erro ao criar usuário.', 'danger');
      }
    });
  }

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

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

  async confirmDelete() {
    if (!this.deleteTarget) return;
    if (!(await confirmDeletionWithTyping('este registro de dados do usuário'))) return;
    const id = this.deleteTarget.id;
    this.service.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');
      }
    });
  }

  trackById(_: number, row: UserDataRow) { return row.id; }
  trackByCliente(_: number, g: UserDataClientGroup) { return g.cliente; }

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

  formatFranquiaLine(value: any): string {
    const n = this.toNullableNumber(value) ?? 0;
    return `${n.toLocaleString('pt-BR', { minimumFractionDigits: 0, maximumFractionDigits: 2 })} GB`;
  }

  private normalizeTipo(row: UserDataRow | null | undefined): 'PF' | 'PJ' {
    const t = (row?.tipoPessoa ?? '').toString().trim().toUpperCase();
    if (t === 'PJ') return 'PJ';
    if (t === 'PF') return 'PF';
    if (row?.cnpj) return 'PJ';
    return 'PF';
  }

  showToast(msg: string, type: 'success' | 'danger') {
    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; }
}
