import React, { useMemo } from 'react';

import {
  Layer,
  Line,
  Rect,
  Stage,
  Text,
} from 'react-konva';

import { Skeleton } from '@/components/ui/skeleton';

import {
  flattenHallValueToElements,
  resolveHallCanvasSize,
  sortHallElementsByPaintOrder,
} from './hallFlat';
import {
  hallPolygonAbsolutePoints,
  hallPolygonLabelLayout,
} from './hallPolygon';
import { hallSectorLabelLayout } from './hallSectorLabel';
import {
  buildHallSeatSmartLabels,
  getHallBlockCornerRadius,
  getHallBlockOnShapeTextFill,
  getHallSeatCornerRadius,
  HALL_ELEMENT_DEFAULTS,
  HALL_SEAT_SIZE,
  HALL_SECTOR,
  hallSeatApiLabelFill,
  hallSeatLabelFontSizeForRect,
  hallSeatRowLabelFill,
  hallSeatRowLabelFontSizeForRect,
  resolveHallElementFill,
} from './hallTheme';

type DialogHallPreviewProps = {
  /** Массив элементов зала или старый объект с `seats` / `elements`. */
  hall: unknown | null;
  width: number;
  height: number;
};

const isHallLoading = (hall: unknown | null) =>
  hall == null || typeof hall === 'string';

const DialogHallPreview = (props: DialogHallPreviewProps) => {
  const { hall, width, height } = props;
  const loading = isHallLoading(hall);

  const geometry = useMemo(() => {
    if (loading) {
      return null;
    }
    const flat = sortHallElementsByPaintOrder(flattenHallValueToElements(hall));
    const canvas = resolveHallCanvasSize(flat);
    return {
      canvas,
      sectors: flat.filter((e) => e.type === 'sector'),
      sectorPolygons: flat.filter((e) => e.type === 'sector_polygon'),
      zones: flat.filter((e) => e.type === 'zone'),
      stages: flat.filter((e) => e.type === 'stage'),
      tables: flat.filter((e) => e.type === 'table'),
      walls: flat.filter((e) => e.type === 'wall'),
      seats: flat.filter((e) => e.type === 'seat'),
    };
  }, [hall, loading]);

  const stageW = geometry?.canvas.width ?? 800;
  const stageH = geometry?.canvas.height ?? 800;

  const scale = useMemo(() => {
    const w = Math.max(1, width);
    const h = Math.max(1, height);
    return Math.min(w / stageW, h / stageH);
  }, [width, height, stageW, stageH]);

  const stageCssW = stageW * scale;
  const stageCssH = stageH * scale;
  const offsetX = (width - stageCssW) / 2;
  const offsetY = (height - stageCssH) / 2;
  const seatSmartLabels = useMemo(
    () => buildHallSeatSmartLabels(geometry?.seats ?? []),
    [geometry],
  );

  return (
    <div
      className="relative overflow-hidden rounded-md bg-white outline-1 outline-slate-300"
      style={{ width, height }}
    >
      {loading && (
        <Skeleton className="absolute inset-0 z-10 rounded-md top-0 left-0 w-full h-full" />
      )}
      <div
        className="absolute"
        style={{
          left: offsetX,
          top: offsetY,
          width: stageCssW,
          height: stageCssH,
        }}
      >
        <Stage
          width={stageW}
          height={stageH}
          scaleX={scale}
          scaleY={scale}
          listening={false}
        >
          <Layer listening={false}>
            {geometry && (geometry.sectors ?? []).map((item: any) => {
              const sectorLabel = hallSectorLabelLayout({
                x: item.x,
                y: item.y,
                width: item.width,
                height: item.height,
                rotation: item.rotation ?? 0,
                fontSize: 14,
              });
              return (
              <React.Fragment key={item._id}>
                <Rect
                  x={item.x}
                  y={item.y}
                  width={item.width}
                  height={item.height}
                  rotation={item.rotation ?? 0}
                  fill={HALL_SECTOR.fill}
                  stroke={HALL_SECTOR.stroke}
                  strokeWidth={HALL_SECTOR.strokeWidth}
                  cornerRadius={getHallBlockCornerRadius('sector')}
                  listening={false}
                />
                <Text
                  x={sectorLabel.x}
                  y={sectorLabel.y}
                  width={sectorLabel.width}
                  offsetX={sectorLabel.offsetX}
                  offsetY={sectorLabel.offsetY}
                  rotation={sectorLabel.rotation}
                  align="center"
                  verticalAlign="middle"
                  text={item.label ?? ''}
                  fontSize={sectorLabel.fontSize}
                  fill={HALL_SECTOR.labelRegular}
                  listening={false}
                />
              </React.Fragment>
              );
            })}
            {geometry && (geometry.sectorPolygons ?? []).map((item: any) => {
              const absPoints = hallPolygonAbsolutePoints(item);
              const sectorLabel = hallPolygonLabelLayout({
                absPoints,
                fontSize: 14,
              }) ?? hallSectorLabelLayout({
                x: item.x,
                y: item.y,
                width: item.width,
                height: item.height,
                rotation: 0,
                fontSize: 14,
              });
              return (
              <React.Fragment key={item._id}>
                <Line
                  x={item.x}
                  y={item.y}
                  points={Array.isArray(item.points) ? item.points : []}
                  closed
                  rotation={item.rotation ?? 0}
                  fill={HALL_SECTOR.fill}
                  stroke={HALL_SECTOR.stroke}
                  strokeWidth={HALL_SECTOR.strokeWidth}
                  listening={false}
                />
                <Text
                  x={sectorLabel.x}
                  y={sectorLabel.y}
                  width={sectorLabel.width}
                  offsetX={sectorLabel.offsetX}
                  offsetY={sectorLabel.offsetY}
                  rotation={sectorLabel.rotation}
                  align="center"
                  verticalAlign="middle"
                  text={item.label ?? ''}
                  fontSize={sectorLabel.fontSize}
                  fill={HALL_SECTOR.labelRegular}
                  listening={false}
                />
              </React.Fragment>
              );
            })}
            {geometry && (geometry.zones ?? []).map((item: any) => {
              const sectorLabel = hallSectorLabelLayout({
                x: item.x,
                y: item.y,
                width: item.width,
                height: item.height,
                rotation: item.rotation ?? 0,
                fontSize: 16,
              });
              return (
              <React.Fragment key={item._id}>
                <Rect
                  x={item.x}
                  y={item.y}
                  width={item.width}
                  height={item.height}
                  rotation={item.rotation ?? 0}
                  fill={HALL_SECTOR.fill}
                  stroke={HALL_SECTOR.stroke}
                  strokeWidth={HALL_SECTOR.strokeWidth}
                  cornerRadius={getHallBlockCornerRadius('zone')}
                  listening={false}
                />
                <Text
                  x={sectorLabel.x}
                  y={sectorLabel.y}
                  width={sectorLabel.width}
                  offsetX={sectorLabel.offsetX}
                  offsetY={sectorLabel.offsetY}
                  rotation={sectorLabel.rotation}
                  align="center"
                  verticalAlign="middle"
                  text={item.label ?? ''}
                  fontSize={sectorLabel.fontSize}
                  fill={HALL_SECTOR.labelNoSeats}
                  listening={false}
                />
              </React.Fragment>
              );
            })}
          </Layer>

          <Layer listening={false}>
            {geometry && (geometry.stages ?? []).map((item: any) => (
              <React.Fragment key={item._id}>
                <Rect
                  x={item.x}
                  y={item.y}
                  width={item.width}
                  height={item.height}
                  rotation={item.rotation ?? 0}
                  fill={HALL_ELEMENT_DEFAULTS.stage.fill}
                  cornerRadius={getHallBlockCornerRadius('stage')}
                  listening={false}
                />
                <Text
                  x={item.x}
                  y={item.y + item.height / 2 - 8}
                  width={item.width}
                  align="center"
                  text={item.label ?? 'Сцена'}
                  fontSize={16}
                  fill={getHallBlockOnShapeTextFill('stage')}
                  listening={false}
                />
              </React.Fragment>
            ))}
            {geometry && (geometry.tables ?? []).map((item: any) => (
              <React.Fragment key={item._id}>
                <Rect
                  x={item.x}
                  y={item.y}
                  width={item.width}
                  height={item.height}
                  rotation={item.rotation ?? 0}
                  fill={HALL_ELEMENT_DEFAULTS.table.fill}
                  cornerRadius={getHallBlockCornerRadius('table')}
                  listening={false}
                />

              </React.Fragment>
            ))}
            {geometry && (geometry.walls ?? []).map((item: any) => (
              <React.Fragment key={item._id}>
                <Rect
                  x={item.x}
                  y={item.y}
                  width={item.width}
                  height={item.height}
                  rotation={item.rotation ?? 0}
                  fill={HALL_ELEMENT_DEFAULTS.wall.fill}
                  cornerRadius={getHallBlockCornerRadius('wall')}
                  listening={false}
                />
              </React.Fragment>
            ))}
            {geometry && (geometry.seats ?? []).map((item: any) => {
              const seatLabel = seatSmartLabels.seatLabelsById[item._id] ?? '';
              const w = typeof item.width === 'number' && Number.isFinite(item.width) && item.width > 0 ? item.width : HALL_SEAT_SIZE;
              const h = typeof item.height === 'number' && Number.isFinite(item.height) && item.height > 0 ? item.height : HALL_SEAT_SIZE;
              const halfW = w / 2;
              const halfH = h / 2;
              const sideLabels = seatSmartLabels.sideRowLabelsBySeatId[item._id];
              const rowLabelFontSize = hallSeatRowLabelFontSizeForRect(w, h);
              const rowLabelGap = Math.max(6, Math.round(w * 0.18));
              const leftRowLabelWidth = sideLabels?.left
                ? Math.max(16, Math.round(sideLabels.left.length * rowLabelFontSize * 0.72) + 4)
                : 0;
              const rightRowLabelWidth = sideLabels?.right
                ? Math.max(16, Math.round(sideLabels.right.length * rowLabelFontSize * 0.72) + 4)
                : 0;
              return (
                <React.Fragment key={item._id}>
                  <Rect
                    x={item.x}
                    y={item.y}
                    offsetX={halfW}
                    offsetY={halfH}
                    width={w}
                    height={h}
                    rotation={item.rotation ?? 0}
                    fill={resolveHallElementFill(item)}
                    cornerRadius={getHallSeatCornerRadius(w, h)}
                    listening={false}
                  />
                  <Text
                    x={item.x}
                    y={item.y}
                    offsetX={halfW}
                    offsetY={halfH}
                    width={w}
                    height={h}
                    rotation={item.rotation ?? 0}
                    align="center"
                    verticalAlign="middle"
                    wrap="none"
                    text={seatLabel}
                    fontSize={hallSeatLabelFontSizeForRect(
                      seatLabel,
                      w,
                      h,
                    )}
                    fontStyle="bold"
                    fontFamily="Arial,sans-serif"
                    fill={hallSeatApiLabelFill()}
                    listening={false}
                  />
                  {sideLabels?.left && (
                    <Text
                      x={item.x - halfW - rowLabelGap - leftRowLabelWidth / 2}
                      y={item.y}
                      offsetX={leftRowLabelWidth / 2}
                      offsetY={h / 2}
                      width={leftRowLabelWidth}
                      height={h}
                      rotation={item.rotation ?? 0}
                      align="right"
                      verticalAlign="middle"
                      wrap="none"
                      text={sideLabels.left}
                      fontSize={rowLabelFontSize}
                      fontStyle="bold"
                      fontFamily="Arial,sans-serif"
                      fill={hallSeatRowLabelFill()}
                      listening={false}
                    />
                  )}
                  {sideLabels?.right && (
                    <Text
                      x={item.x + halfW + rowLabelGap + rightRowLabelWidth / 2}
                      y={item.y}
                      offsetX={rightRowLabelWidth / 2}
                      offsetY={h / 2}
                      width={rightRowLabelWidth}
                      height={h}
                      rotation={item.rotation ?? 0}
                      align="left"
                      verticalAlign="middle"
                      wrap="none"
                      text={sideLabels.right}
                      fontSize={rowLabelFontSize}
                      fontStyle="bold"
                      fontFamily="Arial,sans-serif"
                      fill={hallSeatRowLabelFill()}
                      listening={false}
                    />
                  )}
                </React.Fragment>
              );
            })}
          </Layer>
        </Stage>
      </div>
    </div>
  );
};

export default DialogHallPreview;
