import { activityColor, type HeatmapMode } from './colors'
import { formatCurrency } from './format'
import type { ActivitySimResult, Resource, ResourceType, SimulationResult } from '@/domain/types'

// Nombres y colores por tipo de recurso — única fuente de verdad
export const RESOURCE_TYPE_LABELS: Record<ResourceType, string> = {
  role: 'Roles', person: 'Personas', system: 'Sistemas',
  equipment: 'Equipos', supply: 'Insumos',
}

export const RESOURCE_TYPE_COLORS: Record<ResourceType, string> = {
  role: '#3b82f6', person: '#10b981', system: '#8b5cf6',
  equipment: '#f59e0b', supply: '#64748b',
}

function truncate(s: string, max: number): string {
  return s.length > max ? s.slice(0, max - 1) + '…' : s
}

// ─── Top actividades por costo — barras horizontales ─────────────────────────

export function buildTopActivitiesOption(
  perActivity: ActivitySimResult[],
  mode: HeatmapMode,
  currency: string
): Record<string, unknown> {
  const top10 = perActivity.slice(0, 10)

  return {
    tooltip: {
      trigger: 'axis',
      axisPointer: { type: 'shadow' },
      formatter: (params: unknown[]) => {
        const p = params[0] as { dataIndex: number; value: number }
        const act = top10[p.dataIndex]
        return `<div style="font-size:12px">
          <div style="font-weight:600;margin-bottom:4px">${act.activityName}</div>
          <div>Costo esperado: <strong>${formatCurrency(act.expectedTotalCost, currency)}</strong></div>
          <div>% del total: ${act.percentOfTotal.toFixed(1)}%</div>
          <div>Directo: ${formatCurrency(act.expectedDirectCost, currency)}</div>
          <div>Indirecto: ${formatCurrency(act.expectedIndirectCost, currency)}</div>
        </div>`
      },
    },
    grid: { left: 12, right: 24, top: 8, bottom: 8, containLabel: true },
    xAxis: {
      type: 'value',
      axisLabel: {
        fontSize: 11,
        formatter: (v: number) => {
          if (v === 0) return '0'
          if (v >= 1_000_000) return `${(v / 1_000_000).toFixed(1)}M`
          if (v >= 1_000) return `${(v / 1_000).toFixed(0)}k`
          return String(v)
        },
      },
      splitLine: { lineStyle: { color: '#f1f5f9' } },
    },
    yAxis: {
      type: 'category',
      data: top10.map((a) => truncate(a.activityName, 28)),
      inverse: true,
      axisLabel: { fontSize: 11, color: '#475569', width: 160, overflow: 'truncate' },
      axisTick: { show: false },
      axisLine: { show: false },
    },
    series: [{
      type: 'bar',
      data: top10.map((a) => ({
        value: a.expectedTotalCost,
        itemStyle: { color: activityColor(a, perActivity, mode) },
      })),
      barMaxWidth: 28,
      label: {
        show: true,
        position: 'right',
        fontSize: 10,
        color: '#64748b',
        formatter: (p: { value: number }) => formatCurrency(p.value, currency),
      },
    }],
  }
}

// ─── Composición directo / indirecto — donut ──────────────────────────────────

export function buildCostCompositionOption(
  result: Pick<SimulationResult, 'totalDirectCost' | 'totalIndirectCost' | 'totalCost'>,
  currency: string
): Record<string, unknown> {
  const hasIndirect = result.totalIndirectCost > 0

  return {
    tooltip: {
      trigger: 'item',
      formatter: (p: { name: string; value: number; percent: number }) =>
        `<div style="font-size:12px">
          <div style="font-weight:600;margin-bottom:4px">${p.name}</div>
          <div>${formatCurrency(p.value, currency)} (${p.percent.toFixed(1)}%)</div>
        </div>`,
    },
    legend: {
      bottom: '2%',
      left: 'center',
      itemWidth: 12,
      itemHeight: 12,
      textStyle: { fontSize: 11, color: '#475569' },
    },
    series: [{
      type: 'pie',
      radius: ['48%', '68%'],
      center: ['50%', '44%'],
      avoidLabelOverlap: true,
      itemStyle: { borderRadius: 4, borderColor: '#fff', borderWidth: 2 },
      label: {
        show: true,
        fontSize: 11,
        formatter: (p: { percent: number }) => `${p.percent.toFixed(1)}%`,
      },
      labelLine: { length: 10, length2: 8 },
      emphasis: { label: { fontSize: 13, fontWeight: 'bold' } },
      data: [
        { value: result.totalDirectCost, name: 'Costo directo', itemStyle: { color: '#F59845' } },
        ...(hasIndirect ? [{ value: result.totalIndirectCost, name: 'Costo indirecto (overhead)', itemStyle: { color: '#94a3b8' } }] : []),
      ],
    }],
    graphic: [{
      type: 'text',
      left: 'center',
      top: '38%',
      style: {
        text: formatCurrency(result.totalCost, currency),
        textAlign: 'center',
        fontSize: 13,
        fontWeight: 'bold',
        fill: '#1e293b',
        fontFamily: 'JetBrains Mono, monospace',
      },
    }],
  }
}

// ─── Costo por tipo de recurso — barras verticales ────────────────────────────

interface ResourceTypeTotals {
  byType: Partial<Record<ResourceType, number>>
  byTypeDetails: Partial<Record<ResourceType, { name: string; cost: number }[]>>
  activeTypes: ResourceType[]
}

export function aggregateResourceCosts(
  perActivity: ActivitySimResult[],
  resources: Resource[]
): ResourceTypeTotals {
  const resourceById = new Map(resources.map((r) => [r.id, r]))
  const byType: Partial<Record<ResourceType, number>> = {}
  const byTypeDetails: Partial<Record<ResourceType, { name: string; cost: number }[]>> = {}

  for (const act of perActivity) {
    for (const rb of act.resourceCostBreakdown) {
      if (rb.cost <= 0) continue
      const res = resourceById.get(rb.resourceId)
      if (!res) continue
      byType[res.type] = (byType[res.type] ?? 0) + rb.cost
      if (!byTypeDetails[res.type]) byTypeDetails[res.type] = []
      const existing = byTypeDetails[res.type]!.find((d) => d.name === res.name)
      if (existing) existing.cost += rb.cost
      else byTypeDetails[res.type]!.push({ name: res.name, cost: rb.cost })
    }
  }

  const activeTypes = (Object.keys(RESOURCE_TYPE_LABELS) as ResourceType[]).filter(
    (t) => (byType[t] ?? 0) > 0
  )

  return { byType, byTypeDetails, activeTypes }
}

export function buildCostByResourceOption(
  perActivity: ActivitySimResult[],
  resources: Resource[],
  currency: string
): Record<string, unknown> | null {
  const { byType, byTypeDetails, activeTypes } = aggregateResourceCosts(perActivity, resources)
  if (activeTypes.length === 0) return null

  return {
    tooltip: {
      trigger: 'axis',
      axisPointer: { type: 'shadow' },
      formatter: (params: unknown[]) => {
        const p = params[0] as { dataIndex: number; value: number }
        const type = activeTypes[p.dataIndex]
        const dets = byTypeDetails[type] ?? []
        const detHtml = dets
          .sort((a, b) => b.cost - a.cost)
          .map((d) => `<div style="font-size:11px;padding-left:8px">• ${d.name}: ${formatCurrency(d.cost, currency)}</div>`)
          .join('')
        return `<div style="font-size:12px">
          <div style="font-weight:600;margin-bottom:4px">${RESOURCE_TYPE_LABELS[type]}</div>
          <div>Total: <strong>${formatCurrency(p.value, currency)}</strong></div>${detHtml}
        </div>`
      },
    },
    grid: { left: 12, right: 12, top: 12, bottom: 8, containLabel: true },
    xAxis: {
      type: 'category',
      data: activeTypes.map((t) => RESOURCE_TYPE_LABELS[t]),
      axisLabel: { fontSize: 11, color: '#475569' },
      axisTick: { show: false },
      axisLine: { lineStyle: { color: '#e2e8f0' } },
    },
    yAxis: {
      type: 'value',
      axisLabel: {
        fontSize: 10,
        color: '#94a3b8',
        formatter: (v: number) => {
          if (v >= 1_000_000) return `${(v / 1_000_000).toFixed(1)}M`
          if (v >= 1_000) return `${(v / 1_000).toFixed(0)}k`
          return String(v)
        },
      },
      splitLine: { lineStyle: { color: '#f1f5f9' } },
    },
    series: [{
      type: 'bar',
      data: activeTypes.map((t) => ({
        value: byType[t] ?? 0,
        itemStyle: { color: RESOURCE_TYPE_COLORS[t], borderRadius: [4, 4, 0, 0] },
      })),
      barMaxWidth: 48,
      label: {
        show: true,
        position: 'top',
        fontSize: 10,
        color: '#64748b',
        formatter: (p: { value: number }) => formatCurrency(p.value, currency),
      },
    }],
  }
}
