'use client';

/**
 * Sales Performance — Source → win conversion (Report 01 Chart 4).
 *
 * Stacked horizontal bar per lead source, segments coloured by
 * outcome (won / lost / cancelled / in-flight). PDF-safe (we picked
 * stacked-bar over sankey for that exact reason — locked decision).
 *
 * Each bar normalises to 100% width so source-to-source comparison
 * shows MIX of outcomes regardless of absolute volume. Bar's total
 * count is shown on the right so a 50% win rate on 2 deals doesn't
 * read the same as 50% on 50.
 */

import { cn } from '@/lib/utils';

type Outcome = 'won' | 'lost' | 'cancelled' | 'in_flight';

interface SourceConversionRow {
  source: string;
  counts: Record<Outcome, number>;
  total: number;
}

interface Props {
  rows: SourceConversionRow[];
}

const SOURCE_LABEL: Record<string, string> = {
  website: 'Website',
  referral: 'Referral',
  broker: 'Broker',
  manual: 'Manual',
  unknown: 'Unknown',
};

const OUTCOME_LABEL: Record<Outcome, string> = {
  won: 'Won',
  lost: 'Lost',
  cancelled: 'Cancelled',
  in_flight: 'In flight',
};

// Reuse brand palette. Won = brand-blue (primary success in this app's
// language); Lost = warm rose; Cancelled = muted slate; In-flight =
// soft sage tint so it reads as "still moving" without competing.
const OUTCOME_COLOR: Record<Outcome, string> = {
  won: 'bg-brand-600',
  lost: 'bg-rose-500',
  cancelled: 'bg-slate-400',
  in_flight: 'bg-amber-400',
};

export function SalesSourceConversion({ rows }: Props) {
  if (rows.length === 0) {
    return (
      <div className="py-12 flex flex-col items-center justify-center text-center space-y-2">
        <p className="text-sm text-muted-foreground max-w-xs">
          No leads yet. Source-to-win attribution appears as deals start landing in the pipeline.
        </p>
      </div>
    );
  }

  return (
    <div className="space-y-3">
      {/* Legend */}
      <div className="flex flex-wrap gap-4 text-[11px] text-muted-foreground">
        {(Object.keys(OUTCOME_LABEL) as Outcome[]).map((o) => (
          <span key={o} className="inline-flex items-center gap-1.5">
            <span className={cn('h-2 w-2 rounded-sm', OUTCOME_COLOR[o])} aria-hidden />
            {OUTCOME_LABEL[o]}
          </span>
        ))}
      </div>

      {/* Rows */}
      <div className="space-y-2.5">
        {rows.map((row) => (
          <div
            key={row.source}
            className="grid items-center gap-3"
            style={{ gridTemplateColumns: '120px 1fr 70px' }}
          >
            <div className="text-sm font-medium text-foreground">
              {SOURCE_LABEL[row.source] ?? row.source}
            </div>

            <div
              className="relative h-6 rounded-sm bg-muted/40 overflow-hidden flex"
              role="img"
              aria-label={`${row.source}: ${describeRow(row)}`}
            >
              {(Object.keys(OUTCOME_COLOR) as Outcome[]).map((outcome) => {
                const count = row.counts[outcome];
                if (count === 0) return null;
                const pct = (count / row.total) * 100;
                return (
                  <div
                    key={outcome}
                    className={cn(OUTCOME_COLOR[outcome], 'h-full')}
                    style={{ width: `${pct}%` }}
                    title={`${OUTCOME_LABEL[outcome]}: ${count} (${pct.toFixed(0)}%)`}
                    aria-hidden
                  />
                );
              })}
            </div>

            <span className="text-[11px] text-muted-foreground tabular-nums text-right">
              {row.total} {row.total === 1 ? 'lead' : 'leads'}
            </span>
          </div>
        ))}
      </div>
    </div>
  );
}

function describeRow(row: SourceConversionRow): string {
  return (Object.keys(OUTCOME_LABEL) as Outcome[])
    .filter((o) => row.counts[o] > 0)
    .map((o) => `${row.counts[o]} ${OUTCOME_LABEL[o].toLowerCase()}`)
    .join(', ');
}
