import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { SnackNotifyService } from '../../snack-notify/snack-notify.service';
import { ConfirmationService } from '../../../services/confirmation/confirmation.service';
import { Logger } from '../../../services/logger/logger.service';
import {
  TabItem,
  TabSystemConfig,
  TabSystemState,
  TabSystemActions,
  TabSystemEvents,
  TabOperationResult
} from '../interfaces/tab-system.interface';
import { TabFormConfigService } from './tab-form-config.service';
import { TabFormConfig } from '../../../interfaces/generic-tab-form.interface';

@Injectable({
  providedIn: 'root'
})
export class TabSystemService implements TabSystemActions {
  private logger: Logger;
  private instanceId: string;
  private defaultConfig: TabSystemConfig = {
    maxTabs: 3,
    allowDuplicates: false,
    autoSave: false,
    confirmClose: true,
    autoSelectOnAdd: true
  };

  private stateSubject = new BehaviorSubject<TabSystemState>({
    tabs: [],
    selectedTabIndex: -1,
    maxTabs: 3,
    isLoading: false
  });

  public state$ = this.stateSubject.asObservable();
  private config: TabSystemConfig;
  private events: TabSystemEvents = {};

  constructor(private snackNotifyService: SnackNotifyService, private tabFormConfigService: TabFormConfigService, private confirmationService: ConfirmationService) {
    this.instanceId = Math.random().toString(36).substring(2, 15);
    this.logger = new Logger(`TabSystemService-${this.instanceId}`);
    this.config = { ...this.defaultConfig };
    
    // Configurar Logger para modo silencioso - apenas erros e warnings
    Logger.overrideLogger(['error', 'warn', 'fatal']);
  }

  /**
   * Configura o sistema de abas
   */
  configure(config: Partial<TabSystemConfig>, events?: TabSystemEvents): void {
    this.config = { ...this.defaultConfig, ...config };
    this.events = events || {};
    
    const currentState = this.stateSubject.value;
    this.stateSubject.next({
      ...currentState,
      maxTabs: this.config.maxTabs
    });

    // this.logger.log('TabSystem configurado', { config: this.config });
  }

  /**
   * Adiciona uma nova aba
   */
  async addTab(item: TabItem): Promise<boolean> {
    // this.logger.log('Tentando adicionar aba', { item });
    
    const currentState = this.stateSubject.value;
    
    // Verificar se já existe (se não permite duplicatas)
    if (!this.config.allowDuplicates) {
      // ✨ MELHORIA: Verificação mais robusta para entidades específicas
      const existingIndex = currentState.tabs.findIndex(tab => {
        // Para entidades com ID específico, verificar ID + tipo
        if (item.data?.id && item.data.id !== 'new' && tab.data?.id && tab.data.id !== 'new') {
          return tab.data.id === item.data.id && tab.type === item.type;
        }
        
        // Para abas de lista ou outras, verificar ID da aba + tipo
        return tab.id === item.id && tab.type === item.type;
      });
      
      if (existingIndex !== -1) {
        this.selectTab(existingIndex);
        // this.logger.log('Aba já existe, selecionando', { index: existingIndex });
        return true;
      }
    }

    // Verificar limite máximo
    if (currentState.tabs.length >= this.config.maxTabs) {
      const message = `Foi atingido o número máximo de ${this.config.maxTabs} abas permitidas.`;
      this.snackNotifyService.warning(message, { duration: 4000 });
      this.events.onMaxTabsReached?.();
      // this.logger.warn('Limite máximo de abas atingido', { maxTabs: this.config.maxTabs });
      return false;
    }

    // Adicionar nova aba
    const newTabs = [...currentState.tabs, item];
    const newSelectedIndex = this.config.autoSelectOnAdd ? newTabs.length - 1 : currentState.selectedTabIndex;

    this.stateSubject.next({
      ...currentState,
      tabs: newTabs,
      selectedTabIndex: newSelectedIndex
    });

    this.events.onTabAdded?.(item, newSelectedIndex);
    // this.logger.log('Aba adicionada com sucesso', { item, index: newSelectedIndex });
    
    return true;
  }

  /**
   * Remove uma aba
   */
  async removeTab(index: number): Promise<boolean> {
    const currentState = this.stateSubject.value;
    
    if (index < 0 || index >= currentState.tabs.length) {
      // this.logger.error('Índice de aba inválido', { index });
      return false;
    }

    const tabToRemove = currentState.tabs[index];
    
    // Verificar mudanças não salvas e solicitar confirmação
    if (this.config.confirmClose && tabToRemove.isModified) {
      const confirmed = await this.confirmationService.confirmUnsavedChanges(tabToRemove.title);
      
      if (!confirmed) {
        // this.logger.log('Fechamento de aba cancelado pelo usuário', { tab: tabToRemove });
        return false; // Usuário cancelou o fechamento
      }
      
      // this.logger.log('Usuário confirmou fechamento de aba com mudanças não salvas', { tab: tabToRemove });
    }

    const newTabs = currentState.tabs.filter((_, i) => i !== index);
    let newSelectedIndex = currentState.selectedTabIndex;

    // Ajustar índice selecionado
    if (newTabs.length === 0) {
      newSelectedIndex = -1;
    } else if (index === currentState.selectedTabIndex) {
      newSelectedIndex = Math.min(index, newTabs.length - 1);
    } else if (index < currentState.selectedTabIndex) {
      newSelectedIndex = currentState.selectedTabIndex - 1;
    }

    this.stateSubject.next({
      ...currentState,
      tabs: newTabs,
      selectedTabIndex: newSelectedIndex
    });

    this.events.onTabRemoved?.(tabToRemove, index);
    // this.logger.log('Aba removida', { tab: tabToRemove, index });
    
    return true;
  }

  /**
   * Seleciona uma aba
   */
  selectTab(index: number): void {
    const currentState = this.stateSubject.value;
    
    if (index < 0 || index >= currentState.tabs.length) {
      // this.logger.error('Índice de aba inválido para seleção', { index });
      return;
    }

    if (index === currentState.selectedTabIndex) {
      // this.logger.debug('Aba já está selecionada', { index });
      return;
    }

    this.stateSubject.next({
      ...currentState,
      selectedTabIndex: index
    });

    const selectedTab = currentState.tabs[index];
    this.events.onTabSelected?.(selectedTab, index);
    // this.logger.log('Aba selecionada', { tab: selectedTab, index });
  }

  /**
   * Atualiza dados de uma aba
   */
  updateTab(index: number, data: any): void {
    const currentState = this.stateSubject.value;
    
    if (index < 0 || index >= currentState.tabs.length) {
      // this.logger.error('Índice de aba inválido para atualização', { index });
      return;
    }

    const updatedTabs = [...currentState.tabs];
    updatedTabs[index] = {
      ...updatedTabs[index],
      data: { ...updatedTabs[index].data, ...data },
      isModified: true
    };

    this.stateSubject.next({
      ...currentState,
      tabs: updatedTabs
    });

    this.events.onTabUpdated?.(updatedTabs[index], index);
    // this.logger.log('Aba atualizada', { index, data });
  }

  /**
   * Fecha todas as abas
   */
  async closeAllTabs(): Promise<boolean> {
    const currentState = this.stateSubject.value;
    
    if (this.hasUnsavedChanges() && this.config.confirmClose) {
      // Implementar confirmação
      this.logger.log('Existem mudanças não salvas ao fechar todas as abas');
    }

    this.stateSubject.next({
      ...currentState,
      tabs: [],
      selectedTabIndex: -1
    });

    // this.logger.log('Todas as abas foram fechadas');
    return true;
  }

  /**
   * Verifica se existem mudanças não salvas
   */
  hasUnsavedChanges(): boolean {
    const currentState = this.stateSubject.value;
    return currentState.tabs.some(tab => tab.isModified);
  }

  /**
   * Obtém o estado atual
   */
  getCurrentState(): TabSystemState {
    return this.stateSubject.value;
  }

  /**
   * Obtém a aba atualmente selecionada
   */
  getSelectedTab(): TabItem | null {
    const currentState = this.stateSubject.value;
    const index = currentState.selectedTabIndex;
    
    if (index >= 0 && index < currentState.tabs.length) {
      return currentState.tabs[index];
    }
    
    return null;
  }

  /**
   * Marca uma aba como salva
   */
  markTabAsSaved(index: number): void {
    const currentState = this.stateSubject.value;
    
    if (index < 0 || index >= currentState.tabs.length) {
      return;
    }

    const updatedTabs = [...currentState.tabs];
    updatedTabs[index] = {
      ...updatedTabs[index],
      isModified: false
    };

    this.stateSubject.next({
      ...currentState,
      tabs: updatedTabs
    });

    // this.logger.log('Aba marcada como salva', { index });
  }

  /**
   * Define o estado modificado de uma aba
   */
  setTabModified(index: number, isModified: boolean): void {
    const currentState = this.stateSubject.value;
    
    if (index < 0 || index >= currentState.tabs.length) {
      // this.logger.error('Índice de aba inválido para definir estado modificado', { index });
      return;
    }

    const currentTab = currentState.tabs[index];

    // 🚨 PROTEÇÃO: Só atualizar se realmente mudou
    if (currentTab.isModified === isModified) {
      return;
    }

    const updatedTabs = [...currentState.tabs];
    updatedTabs[index] = {
      ...updatedTabs[index],
      isModified
    };

    this.stateSubject.next({
      ...currentState,
      tabs: updatedTabs
    });

    // this.logger.debug('Estado modificado da aba alterado', { index, isModified });
  }

  /**
   * Define o estado de loading de uma aba
   */
  setTabLoading(index: number, loading: boolean): void {
    const currentState = this.stateSubject.value;
    
    if (index < 0 || index >= currentState.tabs.length) {
      // this.logger.error('Índice de aba inválido para definir loading', { index });
      return;
    }

    const updatedTabs = [...currentState.tabs];
    updatedTabs[index] = {
      ...updatedTabs[index],
      isLoading: loading
    };

    this.stateSubject.next({
      ...currentState,
      tabs: updatedTabs
    });

    // this.logger.log('Estado de loading da aba alterado', { index, loading });
  }

  /**
   * Retorna o ID único da instância do serviço
   */
  getInstanceId(): string {
    return this.instanceId;
  }

  // Novos métodos para integração com formulários genéricos

  /**
   * Abre uma nova aba com formulário genérico para uma entidade
   */
  async openInTab(
    entityType: string, 
    itemData?: any, 
    customConfig?: Partial<TabFormConfig>,
    customTitle?: string
  ): Promise<boolean> {
    const isNew = !itemData || itemData.id === 'new' || !itemData.id;
    const entityName = this.getEntityDisplayName(entityType);
    
    // Criar ID único para a aba baseado no tipo e ID do item
    const tabId = isNew ? `${entityType}-new-${Date.now()}` : `${entityType}-${itemData.id}`;
    
    // Gerar configuração do formulário
    let formConfig;
    try {
      if (customConfig) {
        formConfig = this.tabFormConfigService.createCustomConfig(entityType, customConfig.fields || [], customConfig);
      } else if (entityType === 'driver') {
        // Para drivers, usar configuração genérica (drivers agora gerenciam própria config)
        formConfig = this.tabFormConfigService.getFormConfigWithSubTabs('driver', ['dados', 'endereco']);
      } else {
        formConfig = this.tabFormConfigService.getFormConfig(entityType);
      }
    } catch (error) {
      // this.logger.error('Erro ao gerar formConfig:', error);
      return false;
    }

    // Preparar dados da aba
    const tabItem: TabItem = {
      id: tabId,
      type: entityType,
      title: customTitle || this.resolveTabTitle(formConfig, itemData, entityName, isNew),
      data: {
        ...itemData,
        formConfig,
        id: itemData?.id || 'new'
      },
      isLoading: false,
      isModified: false
    };

    // this.logger.log('Abrindo aba com formulário genérico', { 
    //   entityType, 
    //   tabId,
    //   title: tabItem.title
    // });

    try {
      const result = await this.addTab(tabItem);
      return result;
    } catch (error) {
      // this.logger.error('Erro em addTab:', error);
      return false;
    }
  }

  /**
   * Abre aba para editar um item existente
   */
  async openEditTab(entityType: string, itemData: any, customTitle?: string): Promise<boolean> {
    // this.logger.log('Abrindo aba para edição', { entityType, itemId: itemData?.id });
    
    try {
      const result = await this.openInTab(entityType, itemData, undefined, customTitle);
      return result;
    } catch (error) {
      // this.logger.error('Erro em openEditTab:', error);
      return false;
    }
  }

  /**
   * Abre aba para criar um novo item
   */
  async openCreateTab(entityType: string, initialData?: any, customTitle?: string): Promise<boolean> {
    const newItemData = {
      ...initialData,
      id: 'new'
    };
    
    return this.openInTab(entityType, newItemData, undefined, customTitle);
  }

  /**
   * Abre aba com configuração de formulário personalizada
   */
  async openCustomFormTab(
    entityType: string, 
    formConfig: TabFormConfig, 
    itemData?: any,
    customTitle?: string
  ): Promise<boolean> {
    return this.openInTab(entityType, itemData, formConfig, customTitle);
  }

  /**
   * Obtém nome de exibição para tipo de entidade
   */
  private getEntityDisplayName(entityType: string): string {
    const displayNames: { [key: string]: string } = {
      'driver': 'Motorista',
      'vehicle': 'Veículo',
      'user': 'Usuário',
      'client': 'Cliente',
      'company': 'Empresa',
      'product': 'Produto',
      'order': 'Pedido',
      'invoice': 'Fatura',
      'route': 'Rota'
    };
    
    return displayNames[entityType] || entityType.charAt(0).toUpperCase() + entityType.slice(1);
  }

  /**
   * 🎯 NOVO: Resolve título da aba usando templates dinâmicos
   * 
   * Prioridade:
   * 1. Template do formConfig.title (ex: "Veículo: {{license_plate}}")
   * 2. Fallback padrão (ex: "Veículo: 1")
   */
  private resolveTabTitle(formConfig: any, itemData: any, entityName: string, isNew: boolean): string {
    // 🎯 PRIORIDADE 1: Template do formConfig
    if (formConfig?.title && formConfig.title.includes('{{')) {
      const resolved = this.resolveTemplateString(formConfig.title, itemData || {});
      
      // 🎯 Verificar se o template foi resolvido com sucesso
      if (resolved && !resolved.includes('{{') && !this.isEmptyTemplate(resolved)) {
        return resolved;
      }
      
      // 🎯 Fallback para template vazio
      if (formConfig.titleFallback) {
        return formConfig.titleFallback;
      }
    }
    
    // 🎯 PRIORIDADE 2: Título estático do formConfig
    if (formConfig?.title && !formConfig.title.includes('{{')) {
      return formConfig.title;
    }
    
    // 🎯 PRIORIDADE 3: Fallback padrão
    return isNew ? `Novo ${entityName}` : `${entityName}: ${itemData?.name || itemData?.id || 'Item'}`;
  }

  /**
   * 🎯 NOVO: Resolve template string com placeholders
   * 
   * Substitui {{campo}} pelos valores dos dados
   */
  private resolveTemplateString(template: string, data: any): string {
    return template.replace(/\{\{(.+?)\}\}/g, (match, propName) => {
      const cleanPropName = propName.trim();
      const value = data[cleanPropName];
      
      // 🎯 Se valor existe e não está vazio, usar
      if (value !== null && value !== undefined && value !== '') {
        return value.toString();
      }
      
      // 🎯 Placeholder vazio para ser tratado depois
      return '';
    });
  }

  /**
   * 🎯 NOVO: Verifica se template está vazio após resolução
   */
  private isEmptyTemplate(resolved: string): boolean {
    return resolved.includes(': ') && resolved.endsWith(': ') ||
           resolved.includes(': -') ||
           resolved.trim() === '' ||
           resolved.includes(': ()');
  }

  /**
   * Atualiza a configuração do formulário de uma aba específica
   */
  updateTabFormConfig(index: number, formConfig: TabFormConfig): void {
    const currentState = this.stateSubject.value;
    
    if (index < 0 || index >= currentState.tabs.length) {
      // this.logger.warn('Índice de aba inválido para atualização de config', { index });
      return;
    }

    const updatedTabs = [...currentState.tabs];
    updatedTabs[index] = {
      ...updatedTabs[index],
      data: {
        ...updatedTabs[index].data,
        formConfig
      }
    };

    this.stateSubject.next({
      ...currentState,
      tabs: updatedTabs
    });

    // this.logger.debug('Configuração do formulário da aba atualizada', { index, formConfig });
  }

  /**
   * ========================================
   * 🚀 MÉTODOS GENÉRICOS PARA QUALQUER ENTIDADE
   * ========================================
   */

  /**
   * Abre aba para qualquer entidade com sub-abas específicas
   */
  async openTabWithSubTabs(
    entityType: string,
    itemData?: any, 
    enabledSubTabs: string[] = ['dados','multas','mapa'],
    customTitle?: string,
    sideCardConfig?: any // ✨ Configuração do side card
  ): Promise<boolean> {
    const isNew = !itemData || itemData.id === 'new' || !itemData.id;
    const tabId = isNew ? `${entityType}-new-${Date.now()}` : `${entityType}-${itemData.id}`;
    
    // Gerar configuração com sub-abas específicas
    const formConfig = this.tabFormConfigService.getFormConfigWithSubTabs(entityType, enabledSubTabs);
    
    // ✨ Adicionar configuração do side card se fornecida
    if (sideCardConfig && !isNew) { // Side card apenas para edição, não para criação
      (formConfig as any).sideCard = sideCardConfig;
    }
    
    const entityName = this.getEntityDisplayName(entityType);
    
    const tabItem: TabItem = {
      id: tabId,
      type: entityType,
      title: customTitle || this.resolveTabTitle(formConfig, itemData, entityName, isNew),
      data: {
        ...itemData,
        formConfig,
        id: itemData?.id || 'new'
      },
      isLoading: false,
      isModified: false
    };

    try {
      const result = await this.addTab(tabItem);
      return result;
    } catch (error) {
      // this.logger.error(`Erro em openTabWithSubTabs para ${entityType}:`, error);
      return false;
    }
  }

  /**
   * Configurações pré-definidas para abas de qualquer entidade
   */
  async openTabWithPreset(
    entityType: string,
    preset: string,
    itemData?: any,
    customTitle?: string
  ): Promise<boolean> {
    const formConfig = this.tabFormConfigService.getFormConfigByPreset(entityType, preset);
    
    if (!formConfig) {
      console.error(`Preset '${preset}' não encontrado para entidade '${entityType}'`);
      return false;
    }
    
    const isNew = !itemData || itemData.id === 'new' || !itemData.id;
    const tabId = isNew ? `${entityType}-new-${Date.now()}` : `${entityType}-${itemData.id}`;
    const entityName = this.getEntityDisplayName(entityType);
    
    const tabItem: TabItem = {
      id: tabId,
      type: entityType,
      title: customTitle || this.resolveTabTitle(formConfig, itemData, entityName, isNew),
      data: {
        ...itemData,
        formConfig,
        id: itemData?.id || 'new'
      },
      isLoading: false,
      isModified: false
    };
    
    try {
      const result = await this.addTab(tabItem);
      return result;
    } catch (error) {
      // this.logger.error(`Erro em openTabWithPreset para ${entityType} (${preset}):`, error);
      return false;
    }
  }

  /**
   * Métodos de conveniência para entidades específicas usando API genérica
   */

  // Veículos
  async openVehicleTab(itemData?: any, enabledSubTabs: string[] = ['dados'], customTitle?: string): Promise<boolean> {
    return this.openTabWithSubTabs('vehicle', itemData, enabledSubTabs, customTitle);
  }

  async openVehicleTabWithPreset(preset: 'basic' | 'withDocs' | 'complete', itemData?: any, customTitle?: string): Promise<boolean> {
    return this.openTabWithPreset('vehicle', preset, itemData, customTitle);
  }

  // Usuários
  async openUserTab(itemData?: any, enabledSubTabs: string[] = ['dados'], customTitle?: string): Promise<boolean> {
    return this.openTabWithSubTabs('user', itemData, enabledSubTabs, customTitle);
  }

  async openUserTabWithPreset(preset: 'basic' | 'withAddress' | 'complete', itemData?: any, customTitle?: string): Promise<boolean> {
    return this.openTabWithPreset('user', preset, itemData, customTitle);
  }

  // Clientes
  async openClientTab(itemData?: any, enabledSubTabs: string[] = ['dados'], customTitle?: string): Promise<boolean> {
    return this.openTabWithSubTabs('client', itemData, enabledSubTabs, customTitle);
  }

  async openClientTabWithPreset(preset: 'basic' | 'withAddress' | 'complete', itemData?: any, customTitle?: string): Promise<boolean> {
    return this.openTabWithPreset('client', preset, itemData, customTitle);
  }

  // Empresas
  async openCompanyTab(itemData?: any, enabledSubTabs: string[] = ['dados'], customTitle?: string): Promise<boolean> {
    return this.openTabWithSubTabs('company', itemData, enabledSubTabs, customTitle);
  }

  async openCompanyTabWithPreset(preset: 'basic' | 'withAddress' | 'complete', itemData?: any, customTitle?: string): Promise<boolean> {
    return this.openTabWithPreset('company', preset, itemData, customTitle);
  }

  // Produtos (sem sub-abas por serem simples)
  async openProductTab(itemData?: any, customTitle?: string): Promise<boolean> {
    return this.openInTab('product', itemData, undefined, customTitle);
  }

  async openProductTabWithPreset(preset: 'basic', itemData?: any, customTitle?: string): Promise<boolean> {
    return this.openTabWithPreset('product', preset, itemData, customTitle);
  }

  /**
   * ========================================
   * 🔄 MÉTODOS ESPECÍFICOS MANTIDOS PARA COMPATIBILIDADE
   * ========================================
   */

  /**
   * Abre aba para driver com sub-abas específicas
   * @deprecated Use openTabWithSubTabs('driver', itemData, enabledSubTabs, customTitle) instead
   */
  async openDriverTab(
    itemData?: any, 
    enabledSubTabs: string[] = ['dados', 'endereco'],
    customTitle?: string
  ): Promise<boolean> {
    return this.openTabWithSubTabs('driver', itemData, enabledSubTabs, customTitle);
  }

  /**
   * Configurações pré-definidas para abas de driver
   * @deprecated Use openTabWithPreset('driver', preset, itemData, customTitle) instead
   */
  async openDriverTabWithPreset(
    preset: 'basic' | 'withAddress' | 'withDocs' | 'complete',
    itemData?: any,
    customTitle?: string
  ): Promise<boolean> {
    return this.openTabWithPreset('driver', preset, itemData, customTitle);
  }
} 