import { CHECKBOX_ROW_CLASS, LABEL_CLASS, PANEL_STRONG_CLASS, PRIMARY_BUTTON_CLASS, SECONDARY_BUTTON_CLASS, ALL_ROLES, type ScoreWeights, type SystemRole } from "./shared.js";

type WeightKey = keyof ScoreWeights;

type WeightDefinition = {
  key: WeightKey;
  code: string;
  title: string;
  details: string;
  formula: string;
  example: string;
  range: string;
  warning?: string;
};

const WEIGHT_DEFINITIONS: WeightDefinition[] = [
  {
    key: "skillDepth",
    code: "D",
    title: "Skill Depth",
    details: "Average proficiency across all skills, scaled to 0–100. Expert-heavy profiles score near 100.",
    formula: "D = round((avg_proficiency / 5) × 100)",
    example: "avg 4.0/5 → 80",
    range: "0 = all Beginner · 100 = all Expert",
  },
  {
    key: "skillBreadth",
    code: "B",
    title: "Skill Breadth",
    details: "Number of distinct skills listed. Ten points per skill, capped at 100 for ten or more skills.",
    formula: "B = min(100, skill_count × 10)",
    example: "7 skills → 70",
    range: "0 = no skills · 100 = 10+ skills",
  },
  {
    key: "costEfficiency",
    code: "C",
    title: "Cost Efficiency",
    details: "Inverse LCR versus the organizational maximum. Cheapest resource scores 100, most expensive scores 0.",
    formula: "C = round((1 − LCR / max_LCR) × 100)",
    example: "60€ vs 120€ → 50",
    range: "0 = highest LCR · 100 = lowest LCR",
    warning: "If all resources share the same LCR, everyone scores 0 on this dimension.",
  },
  {
    key: "chargeability",
    code: "A",
    title: "Chargeability",
    details: "Distance from the personal chargeability target over the last 90 days. On target scores 100.",
    formula: "A = max(0, 100 − |target% − actual%| × 2)",
    example: "10 pp off → 80",
    range: "0 = 50+ pp off target · 100 = exactly on target",
  },
  {
    key: "experience",
    code: "E",
    title: "Experience",
    details: "Average years of experience across skills with explicit years data, capped at 10 years.",
    formula: "E = min(100, avg_years × 10)",
    example: "6.5 yrs → 65 · 10+ yrs → 100",
    range: "0 = no years data · 100 = 10+ years average",
  },
];

type ValueScorePanelProps = {
  scoreWeights: ScoreWeights;
  scoreVisibleRoles: SystemRole[];
  weightSum: number;
  weightSumOk: boolean;
  scoreSaved: boolean;
  recomputeResult: { updated: number } | null;
  isSaving: boolean;
  isRecomputing: boolean;
  onUpdateWeight: (key: keyof ScoreWeights, value: number) => void;
  onToggleRole: (role: SystemRole) => void;
  onRecompute: () => void;
  onSave: () => void;
};

export function ValueScorePanel({
  scoreWeights,
  scoreVisibleRoles,
  weightSum,
  weightSumOk,
  scoreSaved,
  recomputeResult,
  isSaving,
  isRecomputing,
  onUpdateWeight,
  onToggleRole,
  onRecompute,
  onSave,
}: ValueScorePanelProps) {
  return (
    <div className={PANEL_STRONG_CLASS}>
      <div className="flex flex-wrap items-start justify-between gap-3">
        <div className="min-w-0 flex-1">
          <h2 className="mb-1 text-sm font-semibold uppercase tracking-wider text-gray-800 dark:text-gray-200">
            Value Score
          </h2>
          <p className="text-xs leading-relaxed text-gray-500 dark:text-gray-400">
            A persistent 0–100 price/quality metric per resource across five weighted dimensions.
            Recompute on demand after changing weights or importing new skill matrices.
          </p>
        </div>
        <div className="whitespace-nowrap rounded-xl border border-gray-200 bg-gray-50 px-3 py-2 font-mono text-[11px] text-gray-700 dark:border-gray-600 dark:bg-gray-700/50 dark:text-gray-300">
          round(<span className="text-brand-600 dark:text-brand-400">D</span>·w₁ +{" "}
          <span className="text-brand-600 dark:text-brand-400">B</span>·w₂ +{" "}
          <span className="text-brand-600 dark:text-brand-400">C</span>·w₃ +{" "}
          <span className="text-brand-600 dark:text-brand-400">A</span>·w₄ +{" "}
          <span className="text-brand-600 dark:text-brand-400">E</span>·w₅)
        </div>
      </div>

      <div>
        <p className="mb-3 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400">
          Dimension Weights — must sum to 100%
        </p>
        <div className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5">
          {WEIGHT_DEFINITIONS.map((definition) => {
            const value = Math.round(scoreWeights[definition.key] * 100);

            return (
              <div
                key={definition.key}
                className="rounded-2xl border border-gray-200 px-4 py-3 dark:border-gray-600"
              >
                <div className="mb-2 flex items-center gap-2">
                  <span className="rounded bg-brand-50 px-1.5 py-0.5 font-mono text-[10px] font-bold text-brand-700 dark:bg-brand-900/30 dark:text-brand-300">
                    {definition.code}
                  </span>
                  <span className="flex-1 text-sm font-semibold text-gray-800 dark:text-gray-100">
                    {definition.title}
                  </span>
                  <span className="w-10 text-right font-mono text-sm font-bold tabular-nums text-brand-600 dark:text-brand-400">
                    {value}%
                  </span>
                </div>
                <input
                  type="range"
                  min={0}
                  max={100}
                  step={5}
                  value={value}
                  onChange={(event) => onUpdateWeight(definition.key, Number(event.target.value) / 100)}
                  className="w-full accent-brand-600"
                />
                <details className="mt-1.5">
                  <summary className="cursor-pointer select-none text-[11px] text-gray-400 hover:text-gray-600 dark:hover:text-gray-300">
                    Show details
                  </summary>
                  <div className="mt-2 space-y-1.5">
                    <p className="text-xs leading-relaxed text-gray-600 dark:text-gray-400">
                      {definition.details}
                    </p>
                    <div className="rounded bg-gray-50 px-2 py-1.5 font-mono text-[11px] text-gray-600 dark:bg-gray-700 dark:text-gray-300">
                      {definition.formula}
                      <span className="ml-2 text-gray-400">{definition.example}</span>
                    </div>
                    <div className="text-[11px] text-gray-400 dark:text-gray-500">
                      {definition.range}
                    </div>
                    {definition.warning ? (
                      <p className="text-[11px] text-amber-600 dark:text-amber-500">
                        {definition.warning}
                      </p>
                    ) : null}
                  </div>
                </details>
              </div>
            );
          })}
        </div>
      </div>

      <div
        className={`flex items-center gap-2 rounded-2xl border px-4 py-2.5 text-sm font-medium ${
          weightSumOk
            ? "border-green-200 bg-green-50 text-green-700 dark:border-green-700 dark:bg-green-900/20 dark:text-green-300"
            : "border-red-200 bg-red-50 text-red-700 dark:border-red-700 dark:bg-red-900/20 dark:text-red-300"
        }`}
      >
        <span>{weightSumOk ? "✓" : "✗"}</span>
        <span>
          Total weight: <span className="font-mono">{Math.round(weightSum * 100)}%</span>
          {weightSumOk ? " — valid" : " — must be exactly 100% to save"}
        </span>
      </div>

      <div className="space-y-2">
        <label className={LABEL_CLASS}>Score visibility — which roles can see the Value Score</label>
        <p className="text-xs text-gray-500 dark:text-gray-400">
          Controls who sees the score column on the Resources list, the breakdown on the Resource
          Detail page, and the Top Value Resources dashboard widget.
        </p>
        <div className="mt-2 flex flex-wrap gap-3">
          {ALL_ROLES.map((role) => (
            <label key={role} className={`${CHECKBOX_ROW_CLASS} cursor-pointer select-none`}>
              <input
                type="checkbox"
                checked={scoreVisibleRoles.includes(role)}
                onChange={() => onToggleRole(role)}
                className="rounded border-gray-300"
              />
              {role}
            </label>
          ))}
        </div>
      </div>

      <div className="space-y-3 border-t border-gray-100 pt-5 dark:border-gray-700">
        <div>
          <p className="mb-2 text-xs font-semibold uppercase tracking-wider text-gray-600 dark:text-gray-400">
            Recompute Scores
          </p>
          <p className="mb-3 text-xs text-gray-500 dark:text-gray-400">
            Scores are not updated automatically. Run this after changing weights or after importing
            new skill matrices.
          </p>
          <div className="flex items-center gap-3">
            <button
              type="button"
              onClick={onRecompute}
              disabled={isRecomputing}
              className={SECONDARY_BUTTON_CLASS}
            >
              {isRecomputing ? "Recomputing…" : "Recompute All Scores"}
            </button>
            {recomputeResult ? (
              <span className="text-sm font-medium text-green-600 dark:text-green-400">
                Updated {recomputeResult.updated} resource
                {recomputeResult.updated !== 1 ? "s" : ""}
              </span>
            ) : null}
          </div>
        </div>
      </div>

      <div className="flex items-center gap-3 pt-1">
        <button
          type="button"
          onClick={onSave}
          disabled={isSaving || !weightSumOk}
          className={PRIMARY_BUTTON_CLASS}
        >
          {isSaving ? "Saving…" : "Save Score Settings"}
        </button>
        {scoreSaved ? (
          <span className="text-sm font-medium text-green-600 dark:text-green-400">Saved!</span>
        ) : null}
      </div>
    </div>
  );
}
