import { clsx } from "clsx";
import type { StaffingRequirement } from "@nexus/shared";
import { trpc } from "~/lib/trpc/client.js";
import { usePermissions } from "~/hooks/usePermissions.js";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
import type { Assignment, SuggestionItem, WizardState } from "./types.js";

interface ReqSuggestionsProps {
  req: StaffingRequirement;
  startDate: string;
  endDate: string;
  assignments: Assignment[];
  onAssign: (resourceId: string, resourceName: string, role: string) => void;
  onUnassign: (resourceId: string) => void;
}

function ReqSuggestions({
  req,
  startDate,
  endDate,
  assignments,
  onAssign,
  onUnassign,
}: ReqSuggestionsProps) {
  const { canViewScores } = usePermissions();
  const { data, isLoading } = trpc.staffing.getSuggestions.useQuery(
    {
      requiredSkills: req.requiredSkills,
      preferredSkills: req.preferredSkills,
      startDate: new Date(startDate),
      endDate: new Date(endDate),
      hoursPerDay: req.hoursPerDay,
      ...(req.chapter ? { chapter: req.chapter } : {}),
    },
    {
      enabled: req.requiredSkills.length > 0 && !!startDate && !!endDate,
      staleTime: 30_000,
    },
  );

  const reqAssignments = assignments.filter((a) => a.requirementId === req.id);
  const assignedCount = reqAssignments.length;

  if (!req.requiredSkills.length) {
    return (
      <p className="text-xs text-amber-600">
        No skills defined for this demand yet. Go back to Step 3 and add required skills — the AI
        will then suggest matching resources here.
      </p>
    );
  }

  if (isLoading) {
    return <p className="text-xs text-gray-400 animate-pulse">Loading suggestions…</p>;
  }

  const suggestions = (data ?? []) as unknown as SuggestionItem[];

  function availBadge(item: SuggestionItem) {
    if (item.availabilityConflicts.length === 0) {
      return (
        <span className="px-1.5 py-0.5 rounded text-[10px] font-medium bg-green-100 text-green-700">
          Available
        </span>
      );
    }
    if (item.currentUtilization >= 100) {
      return (
        <span className="px-1.5 py-0.5 rounded text-[10px] font-medium bg-red-100 text-red-700">
          Unavailable
        </span>
      );
    }
    return (
      <span className="px-1.5 py-0.5 rounded text-[10px] font-medium bg-amber-100 text-amber-700">
        Partial
      </span>
    );
  }

  return (
    <div>
      <p className="text-xs text-gray-500 mb-2">
        Assigned: {assignedCount} / {req.headcount} needed
      </p>
      <div className="space-y-1.5 max-h-52 overflow-y-auto">
        {suggestions.length === 0 && (
          <p className="text-xs text-gray-400">No matching resources found.</p>
        )}
        {suggestions.slice(0, 10).map((item) => {
          const isAssigned = reqAssignments.some((a) => a.resourceId === item.resourceId);
          return (
            <div
              key={item.resourceId}
              className={clsx(
                "flex items-center gap-2 px-2.5 py-1.5 rounded-lg border text-xs",
                isAssigned
                  ? "border-brand-300 bg-brand-50"
                  : "border-gray-200 bg-white hover:border-gray-300",
              )}
            >
              <div className="flex-1 min-w-0">
                <div className="font-medium text-gray-800 truncate">{item.resourceName}</div>
                <div className="text-gray-400 font-mono">{item.eid}</div>
              </div>
              <div className="flex items-center gap-1.5 flex-shrink-0">
                <span className="px-1.5 py-0.5 rounded text-[10px] font-medium bg-gray-100 text-gray-600">
                  Score {item.score}
                </span>
                {canViewScores && item.valueScore != null && (
                  <span
                    className={`px-1.5 py-0.5 rounded text-[10px] font-medium ${
                      item.valueScore >= 70
                        ? "bg-green-100 text-green-700"
                        : item.valueScore >= 40
                          ? "bg-amber-100 text-amber-700"
                          : "bg-red-100 text-red-700"
                    }`}
                    title="Value Score (price/quality)"
                  >
                    ★ {item.valueScore}
                  </span>
                )}
                <span className="text-gray-400">{Math.round(item.currentUtilization)}%</span>
                {availBadge(item)}
              </div>
              {isAssigned ? (
                <button
                  type="button"
                  onClick={() => onUnassign(item.resourceId)}
                  className="flex-shrink-0 px-2 py-0.5 text-xs border border-brand-300 text-brand-700 rounded hover:bg-brand-100"
                >
                  Remove
                </button>
              ) : (
                <button
                  type="button"
                  onClick={() => onAssign(item.resourceId, item.resourceName, req.role)}
                  disabled={assignedCount >= req.headcount}
                  className="flex-shrink-0 px-2 py-0.5 text-xs bg-brand-600 text-white rounded hover:bg-brand-700 disabled:opacity-40"
                >
                  Assign
                </button>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}

interface Step4Props {
  state: WizardState;
  onChange: (patch: Partial<WizardState>) => void;
}

export function Step4Suggestions({ state, onChange }: Step4Props) {
  function assign(requirementId: string, resourceId: string, resourceName: string, role: string) {
    onChange({
      assignments: [...state.assignments, { requirementId, resourceId, resourceName, role }],
    });
  }

  function unassign(requirementId: string, resourceId: string) {
    onChange({
      assignments: state.assignments.filter(
        (a) => !(a.requirementId === requirementId && a.resourceId === resourceId),
      ),
    });
  }

  if (state.staffingReqs.length === 0) {
    return (
      <p className="text-sm text-gray-400 text-center py-8">
        No staffing requirements defined. Go back to Step 3 to add some.
      </p>
    );
  }

  return (
    <div className="space-y-5 max-h-[55vh] overflow-y-auto pr-1">
      <p className="text-xs text-gray-500 flex items-center gap-1">
        AI-powered resource suggestions based on skills, availability, and utilization.
        <InfoTooltip content="Resources are ranked by skill match score, current utilization, and availability in the project period. Assign resources here or leave unfilled to create placeholder demands." />
      </p>
      {state.staffingReqs.map((req) => (
        <div key={req.id} className="border border-gray-200 rounded-lg p-3">
          <div className="flex items-center gap-2 mb-2">
            <span className="font-medium text-sm text-gray-800">{req.role || "Unnamed Role"}</span>
            <span className="text-xs text-gray-400">
              {req.hoursPerDay}h/day · {req.headcount} needed
            </span>
          </div>
          <ReqSuggestions
            req={req}
            startDate={state.startDate}
            endDate={state.endDate}
            assignments={state.assignments}
            onAssign={(resourceId, resourceName, role) =>
              assign(req.id, resourceId, resourceName, role)
            }
            onUnassign={(resourceId) => unassign(req.id, resourceId)}
          />
        </div>
      ))}
    </div>
  );
}
