"use client";

import * as React from "react";
import { UserPlus, Users } from "lucide-react";

import { ReactSelect } from "@/components/ui/react-select";
import { Button } from "@/components/ui/button";
import { ContributorUserPicker } from "@/components/deals/contributor-user-picker";
import { formatTeamLabelForUi } from "@/lib/deal-display";
import { cn } from "@/lib/utils";
import type {
  BulkAssignLeadsInput,
  BulkAssignMode,
} from "@/features/leads/types";

const TEAM_NONE = "__none__";
const TEAM_UNCHANGED = "__unchanged__";

export type BulkAssignFieldsTeam = {
  id: string;
  name: string;
};

export type BulkAssignFieldsValue = {
  team?: string | null;
  /** When false, `team` is not sent on submit (current value is preserved). */
  teamTouched: boolean;
  ownerId?: string | null;
  ownerIdTouched: boolean;
  aeIds: string[];
  aeMode: BulkAssignMode;
  bdrIds: string[];
  bdrMode: BulkAssignMode;
  contributorIds: string[];
  contributorMode: BulkAssignMode;
};

export const emptyBulkAssignFieldsValue: BulkAssignFieldsValue = {
  team: null,
  teamTouched: false,
  ownerId: null,
  ownerIdTouched: false,
  aeIds: [],
  aeMode: "replace",
  bdrIds: [],
  bdrMode: "replace",
  contributorIds: [],
  contributorMode: "replace",
};

/** Build the payload to POST against /deals/bulk-assign for the given leadIds. */
export function buildBulkAssignPayload(
  leadIds: string[],
  value: BulkAssignFieldsValue,
): BulkAssignLeadsInput {
  const payload: BulkAssignLeadsInput = { leadIds };

  if (value.teamTouched) {
    payload.team = value.team ?? null;
  }
  if (value.ownerIdTouched) {
    payload.ownerId = value.ownerId ?? null;
  }
  if (value.aeIds.length > 0 || value.aeMode === "replace") {
    if (value.aeIds.length > 0 || value.aeMode === "replace") {
      // Only include aeIds when the user opened the picker.
    }
  }
  // We send aeIds/bdrIds/contributorIds only when explicitly touched (length > 0
  // OR replace-with-empty is intentional). Easier UX: send when length > 0.
  if (value.aeIds.length > 0) {
    payload.aeIds = value.aeIds;
    payload.aeMode = value.aeMode;
  }
  if (value.bdrIds.length > 0) {
    payload.bdrIds = value.bdrIds;
    payload.bdrMode = value.bdrMode;
  }
  if (value.contributorIds.length > 0) {
    payload.contributorIds = value.contributorIds;
    payload.contributorMode = value.contributorMode;
  }

  return payload;
}

export function hasBulkAssignChanges(value: BulkAssignFieldsValue): boolean {
  if (value.teamTouched) return true;
  if (value.ownerIdTouched) return true;
  if (value.aeIds.length > 0) return true;
  if (value.bdrIds.length > 0) return true;
  if (value.contributorIds.length > 0) return true;
  return false;
}

function teamSlugFor(team: BulkAssignFieldsTeam): string {
  return team.name.toLowerCase().replace(/\s+/g, "-");
}

function ModeToggle({
  value,
  onChange,
  disabled,
}: {
  value: BulkAssignMode;
  onChange: (mode: BulkAssignMode) => void;
  disabled?: boolean;
}) {
  return (
    <div className="inline-flex rounded-lg border border-border/60 bg-white p-0.5 text-[11px] font-semibold">
      <button
        type="button"
        disabled={disabled}
        onClick={() => onChange("replace")}
        className={cn(
          "rounded-md px-2 py-0.5 transition-colors",
          value === "replace"
            ? "bg-accent text-white"
            : "text-gray-500 hover:text-text",
        )}
      >
        Replace
      </button>
      <button
        type="button"
        disabled={disabled}
        onClick={() => onChange("append")}
        className={cn(
          "rounded-md px-2 py-0.5 transition-colors",
          value === "append"
            ? "bg-accent text-white"
            : "text-gray-500 hover:text-text",
        )}
      >
        Add to existing
      </button>
    </div>
  );
}

export type BulkAssignFieldsProps = {
  value: BulkAssignFieldsValue;
  onChange: (next: BulkAssignFieldsValue) => void;
  teams?: BulkAssignFieldsTeam[];
  aeRoleId?: string;
  bdrRoleId?: string;
  /** Optional id->name map so chips render real names rather than ids. */
  labelById?: Record<string, string | undefined>;
  /**
   * When set (e.g. focused row on `/leads/bulk-assign`), show that lead's
   * current team next to the Team control. Omit in modals or when unknown.
   */
  activeLeadTeamDisplay?: string;
  /**
   * When set, AE/BDR pickers only list users on that CRM team roster (owner +
   * members), intersected with role. Omit for org-wide search (e.g. modal).
   */
  teamMemberIdsForRolePickers?: readonly string[];
  /** Richer placeholder when a table row is focused (active lead's current AEs). */
  activeLeadAePickerPlaceholder?: string;
  activeLeadBdrPickerPlaceholder?: string;
  className?: string;
};

/**
 * Shared form fields for bulk-assigning Team / Owner / AE / BDR / Contributors. Used
 * by both the in-list quick modal and the dedicated `/leads/bulk-assign` page.
 */
export function BulkAssignFields({
  value,
  onChange,
  teams = [],
  aeRoleId,
  bdrRoleId,
  labelById,
  activeLeadTeamDisplay,
  teamMemberIdsForRolePickers,
  activeLeadAePickerPlaceholder,
  activeLeadBdrPickerPlaceholder,
  className,
}: BulkAssignFieldsProps) {
  const teamSelectValue = value.teamTouched
    ? value.team === null
      ? TEAM_NONE
      : (value.team ?? TEAM_NONE)
    : TEAM_UNCHANGED;

  const unchangedTeamSelectLabel =
    activeLeadTeamDisplay !== undefined
      ? `Leave unchanged · ${activeLeadTeamDisplay}`
      : "Leave team unchanged";

  const teamOptions = React.useMemo(
    () => [
      { value: TEAM_UNCHANGED, label: unchangedTeamSelectLabel },
      { value: TEAM_NONE, label: "Clear team" },
      ...teams.map((t) => ({
        value: teamSlugFor(t),
        label: formatTeamLabelForUi(t.name),
      })),
    ],
    [teams, unchangedTeamSelectLabel],
  );

  return (
    <div className={cn("flex flex-col gap-4", className)}>
      <div className="space-y-1.5">
        <label className="text-[11px] font-bold uppercase tracking-wider text-gray-500 font-['Lexend_Deca']">
          Team
        </label>
        <ReactSelect
          value={teamSelectValue}
          onValueChange={(val) => {
            if (val === TEAM_UNCHANGED) {
              onChange({ ...value, teamTouched: false, team: null });
            } else if (val === TEAM_NONE) {
              onChange({ ...value, teamTouched: true, team: null });
            } else {
              onChange({ ...value, teamTouched: true, team: val });
            }
          }}
          options={teamOptions}
          placeholder={unchangedTeamSelectLabel}
          triggerClassName="h-10 min-h-10 rounded-xl bg-gray-50 border-gray-200 text-[13px] font-semibold [&>span]:truncate [&>span]:text-left"
        />
      </div>

      <div className="space-y-1.5">
        <label className="text-[11px] font-bold uppercase tracking-wider text-gray-500 font-['Lexend_Deca'] flex items-center gap-1.5">
          <UserPlus size={12} /> Assign Owner
        </label>
        <ContributorUserPicker
          value={value.ownerId ? [value.ownerId] : []}
          onChange={(ids) => {
            if (ids.length === 0) {
              onChange({ ...value, ownerId: null, ownerIdTouched: false });
            } else {
              const pickedId = ids[ids.length - 1];
              onChange({ ...value, ownerId: pickedId, ownerIdTouched: true });
            }
          }}
          placeholder="Leave owner unchanged"
          className="border-gray-200 bg-gray-50"
          labelById={labelById}
          roleId={aeRoleId}
          forBulkAssign
        />
      </div>

      <div className="space-y-1.5">
        <div className="flex items-center justify-between gap-2">
          <label className="text-[11px] font-bold uppercase tracking-wider text-gray-500 font-['Lexend_Deca'] flex items-center gap-1.5">
            <UserPlus size={12} /> Assign AE
          </label>
          <ModeToggle
            value={value.aeMode}
            onChange={(mode) => onChange({ ...value, aeMode: mode })}
            disabled={value.aeIds.length === 0}
          />
        </div>
        <ContributorUserPicker
          value={value.aeIds}
          onChange={(ids) => onChange({ ...value, aeIds: ids })}
          placeholder={activeLeadAePickerPlaceholder ?? "Select AEs"}
          className="border-gray-200 bg-gray-50"
          roleId={aeRoleId}
          labelById={labelById}
          restrictToUserIds={teamMemberIdsForRolePickers}
          forBulkAssign
        />
      </div>

      <div className="space-y-1.5">
        <div className="flex items-center justify-between gap-2">
          <label className="text-[11px] font-bold uppercase tracking-wider text-gray-500 font-['Lexend_Deca'] flex items-center gap-1.5">
            <UserPlus size={12} /> Assign BDR
          </label>
          <ModeToggle
            value={value.bdrMode}
            onChange={(mode) => onChange({ ...value, bdrMode: mode })}
            disabled={value.bdrIds.length === 0}
          />
        </div>
        <ContributorUserPicker
          value={value.bdrIds}
          onChange={(ids) => onChange({ ...value, bdrIds: ids })}
          placeholder={activeLeadBdrPickerPlaceholder ?? "Select BDRs"}
          className="border-gray-200 bg-gray-50"
          roleId={bdrRoleId}
          labelById={labelById}
          restrictToUserIds={teamMemberIdsForRolePickers}
          forBulkAssign
        />
      </div>

      <div className="space-y-1.5">
        <div className="flex items-center justify-between gap-2">
          <label className="text-[11px] font-bold uppercase tracking-wider text-gray-500 font-['Lexend_Deca'] flex items-center gap-1.5">
            <Users size={12} /> Contributors
          </label>
          <ModeToggle
            value={value.contributorMode}
            onChange={(mode) =>
              onChange({ ...value, contributorMode: mode })
            }
            disabled={value.contributorIds.length === 0}
          />
        </div>
        <ContributorUserPicker
          value={value.contributorIds}
          onChange={(ids) => onChange({ ...value, contributorIds: ids })}
          placeholder="Select contributors"
          className="border-gray-200 bg-gray-50"
          labelById={labelById}
          forBulkAssign
        />
      </div>

      <Button
        type="button"
        variant="ghost"
        size="sm"
        onClick={() => onChange(emptyBulkAssignFieldsValue)}
        className="self-end h-8 text-[12px]"
      >
        Reset
      </Button>
    </div>
  );
}
