'use client';

import { useLayoutEffect, useRef, useState, type ReactNode } from 'react';
import { useTranslations } from 'next-intl';
import { ArrowLeft, Plus, Trash2 } from 'lucide-react';
import { Button } from '@/components/ui/shared/Button';
import {
  ResponsiveDialogOverlay,
  ResponsiveDialogPanel,
} from '@/components/ui/shared/ResponsiveDialog';
import type { ProsthesisCatalogEntry } from '@/types/treatment-catalog';
import { prosthesisFamilyTone } from '@/components/shared/catalog-type-colors';
import { prosthesisTypeColorFromCatalog, prosthesisTypeFillAccent } from '@/components/treatment/prosthesisTypeDisplay';
import { prosthesisCatalogIconSrc } from '@/components/treatment/prosthesisCatalogIcons';
import {
  PROSTHESIS_JOB_PATH_SEP,
  prosthesisJobPathParts,
} from '@/components/treatment/prosthesisJobPath';
import {
  catalogByCode,
  categoryCodesInCatalog,
  categoryDisabledForJobs,
  categoryTileColor,
  crownRestorationCode,
  leavesFor,
  subcategoriesFor,
  type AddonSlot,
  type ArchTarget,
  type PickerScope,
} from '@/components/treatment/prosthesisTree';
import { ProsthesisCatalogIcon } from '@/components/ui/treatment/ProsthesisCatalogIcon';

const CHIP_INK = '#14253d';
const PARENT_BACK_INK = '#000000';
const TILE_CLASS =
  'flex min-h-[4.5rem] min-w-0 w-full flex-col items-center justify-center rounded-[var(--radius-md)] border px-2.5 py-2 text-center transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 disabled:cursor-not-allowed disabled:opacity-45';
const CHILD_TILE_CLASS =
  'flex min-h-[3.75rem] min-w-0 w-full flex-col items-center justify-center rounded-[var(--radius-md)] border px-2 py-1 text-center transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 disabled:cursor-not-allowed disabled:opacity-45';
const PARENT_BAR_CLASS =
  'flex min-h-[3.75rem] min-w-0 w-full flex-row items-center justify-start gap-2 rounded-[var(--radius-md)] border px-3 py-1.5 text-start transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 disabled:cursor-not-allowed disabled:opacity-45';
const TILE_TEXT_CLASS =
  'w-full whitespace-normal break-words text-center text-xs font-medium leading-tight sm:text-[13px]';
const TILE_TEXT_CHILD_CLASS =
  'w-full min-w-0 overflow-hidden text-ellipsis whitespace-nowrap text-center text-[11px] font-medium leading-tight sm:text-xs';
const TILE_GRID_CLASS =
  'grid gap-2 [grid-template-columns:repeat(auto-fill,minmax(8rem,1fr))]';
const TILE_GRID_CHILD_CLASS =
  'grid gap-2 [grid-template-columns:repeat(auto-fill,minmax(10.2rem,1fr))]';
const HEADER_BTN_CLASS = 'h-auto min-h-8 w-full px-2 py-1 text-xs leading-tight whitespace-normal';

function tileSurfaceClass(active?: boolean) {
  return active
    ? 'border-primary ring-1 ring-primary/30'
    : 'border-border/70 hover:border-border hover:bg-background-card/70';
}

export type PickerStep =
  | { kind: 'category' }
  | { kind: 'subcategory'; category: string; arch?: ArchTarget }
  | { kind: 'leaves'; category: string; subcategory?: string; arch?: ArchTarget }
  | { kind: 'addon'; slot: AddonSlot };

interface ProsthesisJobPopoverProps {
  open: boolean;
  mobile: boolean;
  catalog: readonly ProsthesisCatalogEntry[];
  step: PickerStep;
  scope: PickerScope;
  lockedArch?: ArchTarget;
  jobCodes: string[];
  tooth: string | null;
  allowCrownAddon: boolean;
  onStep: (step: PickerStep) => void;
  onLockedArchChange?: (arch: ArchTarget) => void;
  onPickLeaf: (code: string, arch?: ArchTarget) => void;
  onPickAddon: (code: string | null, kind: AddonSlot) => void;
  onRemoveJob: (code: string) => void;
  onClear: () => void;
  onClose: () => void;
}

function Tile({
  label,
  color,
  active,
  disabled,
  hint,
  iconSrc,
  compact,
  className,
  onClick,
}: {
  label: string;
  color?: string;
  active?: boolean;
  disabled?: boolean;
  hint?: string;
  iconSrc?: string;
  compact?: boolean;
  className?: string;
  onClick: () => void;
}) {
  const base = className ?? (compact ? CHILD_TILE_CLASS : TILE_CLASS);
  return (
    <button
      type="button"
      title={hint ?? label}
      onClick={onClick}
      disabled={disabled}
      className={`${base} ${compact ? 'gap-0.5' : 'gap-2'} ${tileSurfaceClass(active)}`}
      style={color ? { backgroundColor: color, color: CHIP_INK } : undefined}
    >
      {iconSrc ? <ProsthesisCatalogIcon src={iconSrc} /> : null}
      <span className={compact ? TILE_TEXT_CHILD_CLASS : TILE_TEXT_CLASS}>{label}</span>
    </button>
  );
}

function parentStep(step: PickerStep): PickerStep | null {
  switch (step.kind) {
    case 'category':
      return null;
    case 'addon':
    case 'subcategory':
      return { kind: 'category' };
    case 'leaves':
      return step.subcategory
        ? { kind: 'subcategory', category: step.category, arch: step.arch }
        : { kind: 'category' };
  }
}

function pickerStepKey(step: PickerStep): string {
  switch (step.kind) {
    case 'category':
      return 'category';
    case 'addon':
      return `addon:${step.slot}`;
    case 'subcategory':
      return `sub:${step.category}:${step.arch ?? ''}`;
    case 'leaves':
      return `leaves:${step.category}:${step.subcategory ?? ''}:${step.arch ?? ''}`;
  }
}

export function ProsthesisJobPopover({
  open,
  mobile,
  catalog,
  step,
  scope,
  lockedArch,
  jobCodes,
  tooth,
  allowCrownAddon,
  onStep,
  onLockedArchChange,
  onPickLeaf,
  onPickAddon,
  onRemoveJob,
  onClear,
  onClose,
}: ProsthesisJobPopoverProps) {
  const t = useTranslations('prosthesis');
  const childGridRef = useRef<HTMLDivElement>(null);
  const [branchH, setBranchH] = useState(0);
  const stepKey = pickerStepKey(step);

  useLayoutEffect(() => {
    if (!open || stepKey === 'category') return;
    const grid = childGridRef.current;
    if (!grid) return;

    const sync = () => {
      const first = grid.firstElementChild;
      if (!(first instanceof HTMLElement)) return;
      setBranchH(first.offsetHeight);
    };

    sync();
    const ro = new ResizeObserver(sync);
    ro.observe(grid);
    grid.addEventListener('animationend', sync);
    return () => {
      ro.disconnect();
      grid.removeEventListener('animationend', sync);
    };
  }, [open, stepKey]);

  if (!open) return null;

  const categories = categoryCodesInCatalog(catalog, scope);
  const byCode = catalogByCode(catalog);
  const crownLeaves = leavesFor(catalog, 'crown', undefined, 'tooth');
  const currentCrown = crownRestorationCode(jobCodes, byCode) ?? '';
  const hasLeaf = jobCodes.length > 0;
  const archForLeaves =
    step.kind === 'leaves' || step.kind === 'subcategory' ? step.arch : lockedArch;

  function categoryLabel(code: string) {
    return t(`category_${code}` as never);
  }
  function subLabel(code: string) {
    return t(`sub_${code}` as never);
  }

  const back = parentStep(step);

  function openCategory(code: string) {
    if (categoryDisabledForJobs(code, jobCodes, byCode)) return;
    const subs = subcategoriesFor(catalog, code, scope);
    const arch = scope === 'arch' ? lockedArch : undefined;
    if (subs.length > 0) {
      onStep({ kind: 'subcategory', category: code, arch });
      return;
    }
    onStep({ kind: 'leaves', category: code, arch });
  }

  function leafTile(leaf: ProsthesisCatalogEntry) {
    const path = prosthesisJobPathParts(leaf.code, catalog, (key) => t(key as never));
    const underIndirectSub =
      leaf.category === 'indirect' && step.kind === 'leaves' && Boolean(step.subcategory);
    return (
      <Tile
        key={leaf.code}
        label={underIndirectSub ? path.leaf : leaf.label}
        compact
        iconSrc={prosthesisCatalogIconSrc(leaf)}
        color={prosthesisTypeColorFromCatalog(leaf.code, catalog)}
        active={jobCodes.includes(leaf.code)}
        onClick={() => onPickLeaf(leaf.code, archForLeaves)}
      />
    );
  }

  const addonTiles: ReactNode[] = [];
  if (scope === 'tooth' && allowCrownAddon && crownLeaves.length > 0) {
    const addonActive = step.kind === 'addon' && step.slot === 'crown';
    const openAddon = () =>
      onStep(addonActive ? { kind: 'category' } : { kind: 'addon', slot: 'crown' });
    if (currentCrown) {
      addonTiles.push(
        <Tile
          key="slot-crown"
          className={`${TILE_CLASS} h-full`}
          compact
          label={byCode.get(currentCrown)?.label ?? currentCrown}
          iconSrc={prosthesisCatalogIconSrc(
            byCode.get(currentCrown) ?? { code: currentCrown, category: 'crown' },
          )}
          color={prosthesisTypeColorFromCatalog(currentCrown, catalog)}
          active={addonActive}
          onClick={openAddon}
        />,
      );
    } else {
      addonTiles.push(
        <button
          key="slot-crown"
          type="button"
          title={t('addonCrownCanBeAdded')}
          aria-pressed={addonActive}
          onClick={openAddon}
          className={`${TILE_CLASS} h-full ${tileSurfaceClass(addonActive)}`}
        >
          <span className="inline-flex max-w-full items-center justify-center gap-1 rounded-[var(--radius-md)] border border-dashed border-border px-3 py-1.5 text-sm font-medium text-text-primary">
            <Plus className="h-3.5 w-3.5 shrink-0" aria-hidden />
            <span className="whitespace-normal break-words text-center leading-tight">
              {t('addonCrownCanBeAdded')}
            </span>
          </span>
        </button>,
      );
    }
  }

  let selectedNode: { label: string; color?: string; iconSrc?: string } | null = null;
  let childTiles: ReactNode[] = [];
  let childrenKey = 'root';

  switch (step.kind) {
    case 'category':
      childTiles = categories.map((code) => {
        const disabled = categoryDisabledForJobs(code, jobCodes, byCode);
        return (
          <Tile
            key={code}
            label={categoryLabel(code)}
            iconSrc={prosthesisCatalogIconSrc({ category: code })}
            color={categoryTileColor(code)}
            disabled={disabled}
            hint={disabled ? t('categoryDisabledHint') : undefined}
            onClick={() => openCategory(code)}
          />
        );
      });
      break;
    case 'addon':
      selectedNode = {
        label: t('slotCrown'),
        color: categoryTileColor('crown'),
        iconSrc: prosthesisCatalogIconSrc({ category: 'crown' }),
      };
      childrenKey = 'addon-crown';
      childTiles = [
        <Tile
          key="none"
          compact
          label={t('addonNone')}
          active={!currentCrown}
          onClick={() => onPickAddon(null, 'crown')}
        />,
        ...crownLeaves.map((opt) => (
          <Tile
            key={opt.code}
            compact
            label={opt.label}
            iconSrc={prosthesisCatalogIconSrc(opt)}
            color={prosthesisTypeColorFromCatalog(opt.code, catalog)}
            active={currentCrown === opt.code}
            onClick={() => onPickAddon(opt.code, 'crown')}
          />
        )),
      ];
      break;
    case 'subcategory': {
      const parentFill = categoryTileColor(step.category);
      selectedNode = {
        label: categoryLabel(step.category),
        color: parentFill,
        iconSrc: prosthesisCatalogIconSrc({ category: step.category }),
      };
      childrenKey = `sub-${step.category}`;
      childTiles = [
        ...subcategoriesFor(catalog, step.category, scope).map((sub, i) => (
          <Tile
            key={sub}
            compact
            label={subLabel(sub)}
            iconSrc={prosthesisCatalogIconSrc({ category: step.category, subcategory: sub })}
            color={prosthesisFamilyTone(parentFill, i + 1)}
            onClick={() =>
              onStep({
                kind: 'leaves',
                category: step.category,
                subcategory: sub,
                arch: step.arch,
              })
            }
          />
        )),
        ...leavesFor(catalog, step.category, undefined, scope).map(leafTile),
      ];
      break;
    }
    case 'leaves':
      if (step.subcategory) {
        selectedNode = {
          label: subLabel(step.subcategory),
          color: prosthesisFamilyTone(categoryTileColor(step.category), 1),
          iconSrc: prosthesisCatalogIconSrc({
            category: step.category,
            subcategory: step.subcategory,
          }),
        };
        childrenKey = `leaves-${step.category}-${step.subcategory}`;
        childTiles = leavesFor(catalog, step.category, step.subcategory, scope).map(leafTile);
      } else {
        selectedNode = {
          label: categoryLabel(step.category),
          color: categoryTileColor(step.category),
          iconSrc: prosthesisCatalogIconSrc({ category: step.category }),
        };
        childrenKey = `leaves-${step.category}`;
        childTiles = leavesFor(catalog, step.category, undefined, scope).map(leafTile);
      }
      break;
  }

  const tileGrid = (
    <div
      key={childrenKey}
      ref={childGridRef}
      className={`picker-expand min-w-0 flex-1 ${
        selectedNode ? TILE_GRID_CHILD_CLASS : TILE_GRID_CLASS
      }${selectedNode ? '' : ' h-full min-h-0 [grid-auto-rows:minmax(4.5rem,1fr)]'}`}
    >
      {childTiles}
    </div>
  );

  const branchColor = selectedNode?.color ?? 'var(--color-border-strong)';
  const tileRow = selectedNode ? (
    <div className="flex min-h-0 flex-col gap-2">
      <button
        type="button"
        onClick={() => {
          if (back) onStep(back);
        }}
        disabled={!back}
        className={PARENT_BAR_CLASS}
        style={
          selectedNode.color
            ? { backgroundColor: selectedNode.color, color: CHIP_INK }
            : undefined
        }
        aria-label={t('pickerBack')}
      >
        <ArrowLeft
          className="h-4 w-4 shrink-0 rtl:rotate-180"
          style={{ color: PARENT_BACK_INK }}
          aria-hidden
        />
        {selectedNode.iconSrc ? (
          <ProsthesisCatalogIcon src={selectedNode.iconSrc} size="sm" />
        ) : null}
        <span className="min-w-0 flex-1 whitespace-normal break-words text-start text-xs font-medium leading-tight sm:text-[13px]">
          {selectedNode.label}
        </span>
      </button>
      <div className="flex items-start">
        <div className="relative w-3 shrink-0" style={{ height: branchH || undefined }} aria-hidden>
          <span
            className="absolute w-0.5"
            style={{
              backgroundColor: branchColor,
              insetInlineStart: 'calc(50% - 1px)',
              top: 0,
              height: '50%',
            }}
          />
          <span
            className="absolute h-0.5"
            style={{
              backgroundColor: branchColor,
              top: 'calc(50% - 1px)',
              insetInlineStart: '50%',
              width: '50%',
            }}
          />
        </div>
        {tileGrid}
      </div>
    </div>
  ) : (
    tileGrid
  );

  const title =
    scope === 'arch'
      ? lockedArch === 'both'
        ? t('pickerArchBoth')
        : lockedArch === 'lower'
          ? t('pickerArchLower')
          : t('pickerArchUpper')
      : tooth
        ? t('pickerTooth', { tooth })
        : t('pickerTitle');

  const jobChips =
    jobCodes.length === 0 ? (
      <p className="text-xs text-text-muted">{t('noneYet')}</p>
    ) : (
      <div className="flex flex-wrap gap-1.5">
        {jobCodes.map((code) => {
          const path = prosthesisJobPathParts(code, catalog, (key) => t(key as never));
          const color = prosthesisTypeColorFromCatalog(code, catalog);
          const trashColor = prosthesisTypeFillAccent(color);
          return (
            <span
              key={code}
              className="inline-flex items-stretch overflow-hidden rounded-[var(--radius-md)] border text-[11px] font-medium"
              style={{
                backgroundColor: color,
                color: CHIP_INK,
                borderColor: 'rgba(0,0,0,0.16)',
              }}
            >
              <span className="inline-flex items-center px-2 py-0.5">
                {path.ancestors.length > 0 ? (
                  <span className="opacity-70">
                    {path.ancestors.join(PROSTHESIS_JOB_PATH_SEP)}
                    {PROSTHESIS_JOB_PATH_SEP}
                  </span>
                ) : null}
                {path.leaf}
              </span>
              <button
                type="button"
                className="inline-flex items-center justify-center border-s px-1.5 transition-colors hover:brightness-90"
                style={{
                  borderColor: trashColor,
                  color: trashColor,
                }}
                aria-label={t('removeJob')}
                onClick={(e) => {
                  e.stopPropagation();
                  onRemoveJob(code);
                }}
              >
                <Trash2 className="lucide-inherit h-3.5 w-3.5" aria-hidden />
              </button>
            </span>
          );
        })}
      </div>
    );

  const body = (
    <div className="grid h-full min-h-0 flex-1 grid-cols-[4fr_1fr]">
      <section className="flex min-h-0 min-w-0 flex-col gap-2.5 border-e border-border pe-3">
        <p className="shrink-0 text-xs font-semibold leading-none text-text-primary">{title}</p>
        {scope === 'arch' && onLockedArchChange ? (
          <div
            className="flex h-8 w-1/2 shrink-0 rounded-[var(--radius-md)] border border-border p-0.5"
            role="group"
            aria-label={title}
          >
            {(['upper', 'lower', 'both'] as const).map((arch) => (
              <button
                key={arch}
                type="button"
                onClick={() => onLockedArchChange(arch)}
                className={`h-full min-w-0 flex-1 rounded-[var(--radius-sm)] px-2 text-xs font-medium leading-tight ${
                  lockedArch === arch
                    ? 'bg-primary text-white'
                    : 'text-text-secondary hover:text-text-primary'
                }`}
              >
                {t(`arch_${arch}`)}
              </button>
            ))}
          </div>
        ) : null}
        <div className="shrink-0">{jobChips}</div>
        <p className="shrink-0 text-[10px] leading-tight text-text-muted">
          {scope === 'arch' ? t('clearHintArch') : t('clearHint')}
        </p>
        <div className="min-h-0 min-w-0 flex-1 overflow-y-auto overflow-x-hidden pe-0.5">
          {tileRow}
        </div>
      </section>
      <section className="flex min-h-0 min-w-0 flex-col gap-1 ps-3">
        <div className="flex shrink-0 flex-col gap-1">
          <Button
            type="button"
            variant="outline"
            size="sm"
            className={HEADER_BTN_CLASS}
            disabled={!hasLeaf}
            onClick={onClear}
          >
            {scope === 'arch' ? t('clearArch') : t('clear')}
          </Button>
          <Button
            type="button"
            variant="primary"
            size="sm"
            className={HEADER_BTN_CLASS}
            onClick={onClose}
          >
            {t('done')}
          </Button>
        </div>
        {addonTiles.length > 0 ? (
          <div className="flex min-h-0 flex-1 flex-col gap-1">
            <p className="shrink-0 text-[10px] font-medium leading-tight text-text-muted">
              {t('suggestionsLabel')}
            </p>
            <div className="min-h-0 flex-1">{addonTiles}</div>
          </div>
        ) : null}
      </section>
    </div>
  );

  if (mobile) {
    return (
      <ResponsiveDialogOverlay onBackdropClick={onClose}>
        <ResponsiveDialogPanel
          role="dialog"
          aria-modal="true"
          maxWidthClass="sm:max-w-2xl"
          className="max-h-[90dvh] flex flex-col"
        >
          <h4 className="sr-only">{t('pickerTitle')}</h4>
          <div className="min-h-0 flex-1 overflow-hidden">{body}</div>
        </ResponsiveDialogPanel>
      </ResponsiveDialogOverlay>
    );
  }

  return (
    <div className="absolute inset-0 z-30 pointer-events-none">
      <button
        type="button"
        className="absolute inset-0 bg-background-primary/55 pointer-events-auto"
        aria-label={t('done')}
        onClick={onClose}
      />
      <div
        className="absolute inset-0 z-10 pointer-events-auto flex flex-col overflow-hidden rounded-[var(--radius-md)] border border-border bg-background-secondary px-3 pb-3 pt-2 shadow-lg"
        role="dialog"
        onClick={(e) => e.stopPropagation()}
        onPointerDown={(e) => e.stopPropagation()}
      >
        <h4 className="sr-only">{t('pickerTitle')}</h4>
        {body}
      </div>
    </div>
  );
}
