import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, DataSource } from 'typeorm';
import { Demanda } from '../demandas/entities/demanda.entity';
import { Proposta } from '../propostas/entities/proposta.entity';
import { OrdemServico } from '../ordens-servico/entities/ordem-servico.entity';
import { OrcamentoPlanejado } from '../orcamento/entities/orcamento-planejado.entity';
import { WorkflowAprovacao } from '../workflow/entities/workflow-aprovacao.entity';
import { Alerta } from './entities/alerta.entity';
import { Fornecedor } from '../fornecedores/entities/fornecedor.entity';
import { Categoria } from '../categorias/entities/categoria.entity';

@Injectable()
export class DashboardService {
  constructor(
    @InjectRepository(Demanda) private demandaRepo: Repository<Demanda>,
    @InjectRepository(Proposta) private propostaRepo: Repository<Proposta>,
    @InjectRepository(OrdemServico) private osRepo: Repository<OrdemServico>,
    @InjectRepository(OrcamentoPlanejado) private orcRepo: Repository<OrcamentoPlanejado>,
    @InjectRepository(WorkflowAprovacao) private wfRepo: Repository<WorkflowAprovacao>,
    @InjectRepository(Alerta) private alertaRepo: Repository<Alerta>,
    @InjectRepository(Fornecedor) private fornecedorRepo: Repository<Fornecedor>,
    @InjectRepository(Categoria) private categoriaRepo: Repository<Categoria>,
    private ds: DataSource,
  ) {}

  async indicadores() {
    const demandas = await this.demandaRepo.find();
    const os = await this.osRepo.find();
    const wf = await this.wfRepo.find();
    const alertas = await this.alertaRepo.find({ where: { lido: false } });

    return {
      demandas_abertas: demandas.filter(d => ['aberta', 'em_escopo'].includes(d.status)).length,
      em_cotacao: demandas.filter(d => d.status === 'em_cotacao').length,
      pendentes: demandas.filter(d => ['propostas_recebidas', 'em_comparacao'].includes(d.status)).length,
      em_aprovacao: wf.filter(w => ['pendente', 'em_andamento'].includes(w.status)).length,
      os_ativas: os.filter(o => ['emitida', 'em_execucao'].includes(o.status)).length,
      alertas: alertas.length,
    };
  }

  async demandasPorStatus() {
    const demandas = await this.demandaRepo.find();
    const statusCount: Record<string, number> = {};
    for (const d of demandas) {
      statusCount[d.status] = (statusCount[d.status] || 0) + 1;
    }
    return Object.entries(statusCount).map(([name, value]) => ({ name, value }));
  }

  async consumoOrcamento(ano: number, centroCustoId?: string, categoriaId?: string) {
    const where: any = { ano };
    if (centroCustoId) where.centro_custo_id = centroCustoId;
    if (categoriaId) where.categoria_id = categoriaId;
    const items = await this.orcRepo.find({ where });
    const meses = ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'];
    const byMonth: Record<number, any> = {};
    for (const item of items) {
      if (!byMonth[item.mes]) byMonth[item.mes] = { name: meses[item.mes - 1], planejado: 0, comprometido: 0, realizado: 0 };
      byMonth[item.mes].planejado += item.valor_planejado;
      byMonth[item.mes].comprometido += item.valor_comprometido;
      byMonth[item.mes].realizado += item.valor_realizado;
    }
    return Object.values(byMonth).sort((a: any, b: any) => {
      const ai = meses.indexOf(a.name);
      const bi = meses.indexOf(b.name);
      return ai - bi;
    });
  }

  async demandasDetalhe(status: string) {
    const demandas = await this.demandaRepo.find();
    const categorias = await this.categoriaRepo.find();
    const catMap: Record<string, string> = {};
    categorias.forEach(c => { catMap[c.id] = c.nome; });

    let filtered: Demanda[];
    switch (status) {
      case 'abertas':
        filtered = demandas.filter(d => ['aberta', 'em_escopo'].includes(d.status));
        break;
      case 'em_cotacao':
        filtered = demandas.filter(d => d.status === 'em_cotacao');
        break;
      case 'em_aprovacao':
        filtered = demandas.filter(d => ['propostas_recebidas', 'em_comparacao'].includes(d.status));
        break;
      case 'concluidas':
        filtered = demandas.filter(d => d.status === 'concluida');
        break;
      default:
        filtered = demandas.filter(d => d.status === status);
    }

    return filtered.map(d => ({
      id: d.id,
      numero: d.numero,
      titulo: d.titulo,
      categoria: catMap[d.categoria_id] || '-',
      status: d.status,
      data: d.created_at,
      valor_estimado: d.valor_estimado,
    }));
  }

  async categoriasQuantidade() {
    const demandas = await this.demandaRepo.find();
    const categorias = await this.categoriaRepo.find();
    const catMap: Record<string, string> = {};
    categorias.forEach(c => { catMap[c.id] = c.nome; });

    const counts: Record<string, number> = {};
    for (const d of demandas) {
      const catName = catMap[d.categoria_id] || 'Outros';
      counts[catName] = (counts[catName] || 0) + 1;
    }

    const colors = ['#E65100', '#1A237E', '#FF8F00', '#757575', '#4CAF50', '#9C27B0', '#00BCD4', '#F44336'];
    return Object.entries(counts).map(([name, value], i) => ({
      name,
      value,
      color: colors[i % colors.length],
    }));
  }

  async busca(q: string) {
    if (!q || q.trim().length < 2) return { demandas: [], orcamentos: [] };
    const term = q.toLowerCase();
    
    const demandas = await this.demandaRepo.find();
    const categorias = await this.categoriaRepo.find();
    const catMap: Record<string, string> = {};
    categorias.forEach(c => { catMap[c.id] = c.nome; });

    const matchedDemandas = demandas.filter(d => 
      d.titulo?.toLowerCase().includes(term) ||
      (catMap[d.categoria_id] || '').toLowerCase().includes(term) ||
      String(d.numero).includes(term)
    ).slice(0, 10).map(d => ({
      id: d.id, numero: d.numero, titulo: d.titulo,
      categoria: catMap[d.categoria_id] || '-', status: d.status,
    }));

    return { demandas: matchedDemandas };
  }

  async alertas(usuarioId?: string) {
    const where: any = { lido: false };
    if (usuarioId) where.usuario_id = usuarioId;
    return this.alertaRepo.find({ where, order: { created_at: 'DESC' }, take: 20 });
  }

  async marcarAlertaLido(id: string) {
    await this.alertaRepo.update(id, { lido: true });
  }

  async esgIndicadores() {
    // Categorias with tipo_manutencao
    const categorias = await this.categoriaRepo.find();
    const catMap: Record<string, any> = {};
    categorias.forEach(c => { catMap[c.id] = c; });

    const demandas = await this.demandaRepo.find();
    const fornecedores = await this.fornecedorRepo.find({ where: { ativo: true } });

    // Classify demandas by tipo_manutencao from their category
    let preventivas = 0, corretivas = 0, emergenciais = 0, totalClassificada = 0;
    const demandasAltoImpacto: any[] = [];

    for (const d of demandas) {
      const cat = catMap[d.categoria_id];
      if (cat?.tipo_manutencao) {
        totalClassificada++;
        if (cat.tipo_manutencao === 'Preventiva') preventivas++;
        else if (cat.tipo_manutencao === 'Corretiva') corretivas++;
        else if (cat.tipo_manutencao === 'Emergencial') emergenciais++;
      }
      if (d.impacto_ambiental_demanda === 'Alto' || (cat?.impacto_ambiental_esperado === 'Alto' && !d.impacto_ambiental_demanda)) {
        demandasAltoImpacto.push({ id: d.id, numero: d.numero, titulo: d.titulo, status: d.status });
      }
    }

    // Fornecedores ESG
    const esgInterm = fornecedores.filter(f => f.classificacao_esg === 'Intermediário' || f.classificacao_esg === 'Avançado').length;
    const esgBasico = fornecedores.filter(f => f.classificacao_esg === 'Básico').length;

    // Evolução mensal preventiva (by created_at month)
    const evolucaoPreventiva: Record<number, number> = {};
    for (const d of demandas) {
      const cat = catMap[d.categoria_id];
      if (cat?.tipo_manutencao === 'Preventiva' && d.created_at) {
        const mes = new Date(d.created_at).getMonth() + 1;
        evolucaoPreventiva[mes] = (evolucaoPreventiva[mes] || 0) + 1;
      }
    }
    const meses = ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'];
    const evolucao = meses.map((name, i) => ({ name, preventivas: evolucaoPreventiva[i + 1] || 0 }));

    return {
      pct_preventivas: totalClassificada > 0 ? Math.round(preventivas / totalClassificada * 100) : 0,
      pct_corretivas: totalClassificada > 0 ? Math.round(corretivas / totalClassificada * 100) : 0,
      pct_emergenciais: totalClassificada > 0 ? Math.round(emergenciais / totalClassificada * 100) : 0,
      total_preventivas: preventivas,
      total_corretivas: corretivas,
      total_emergenciais: emergenciais,
      pct_fornecedores_esg_bom: fornecedores.length > 0 ? Math.round(esgInterm / fornecedores.length * 100) : 0,
      fornecedores_esg_basico: esgBasico,
      fornecedores_esg_intermediario_avancado: esgInterm,
      total_fornecedores: fornecedores.length,
      demandas_alto_impacto: demandasAltoImpacto,
      demandas_alto_impacto_count: demandasAltoImpacto.length,
      evolucao_preventiva: evolucao,
    };
  }
}
