import React, { useMemo } from 'react';

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

import type {
  HallSeatType,
  HallSectorType,
  HallStageType,
  HallTableType,
  HallType,
  HallWallType,
  HallZoneType,
} from '@/api/types';

import {
  formatHallSeatRowSlashNumber,
  getHallBlockCornerRadius,
  getHallBlockOnShapeTextFill,
  HALL_ELEMENT_DEFAULTS,
  HALL_SEAT_SIZE,
  HALL_SECTOR,
  HALL_STAGE_SIZE,
  hallSeatApiLabelFill,
  hallSeatLabelFontSizeForRect,
  resolveHallSeatApiFill,
} from './hallTheme';

type PreviewHallGeometry = {
  sectors: HallSectorType[];
  zones: HallZoneType[];
  stages: HallStageType[];
  tables: HallTableType[];
  walls: HallWallType[];
  seats: HallSeatType[];
};

function hallGeometryItemCount(h: HallType): number {
  return (
    (h.seats?.length ?? 0)
    + (h.tables?.length ?? 0)
    + (h.stages?.length ?? 0)
    + (h.walls?.length ?? 0)
    + (h.zones?.length ?? 0)
    + (h.sectors?.length ?? 0)
  );
}

function editorSeatToPreviewApi(e: any): HallSeatType {
  const out: HallSeatType = { id: e.id, x: e.x, y: e.y };
  if (e.radius != null) {
    out.radius = e.radius;
  }
  if (e.seatNumber != null) {
    out.seatNumber = e.seatNumber;
  }
  if (e.seatRow != null) {
    out.seatRow = e.seatRow;
  }
  if (e.beltId != null) {
    out.beltId = e.beltId;
  }
  if (e.sectorId != null) {
    out.sectorId = e.sectorId;
  }
  if (e.sectorName != null) {
    out.sectorName = e.sectorName;
  }
  if (e.rotation != null) {
    out.rotation = e.rotation;
  }
  return out;
}

function legacyElementsToPreviewGeometry(elements: any[]): PreviewHallGeometry {
  const out: PreviewHallGeometry = {
    sectors: [],
    zones: [],
    stages: [],
    tables: [],
    walls: [],
    seats: [],
  };
  for (const e of elements) {
    switch (e.type) {
      case 'sector':
        out.sectors.push({
          id: e.id,
          x: e.x,
          y: e.y,
          width: e.width,
          height: e.height,
          rotation: e.rotation,
          label: e.label,
        });
        break;
      case 'zone':
        out.zones.push({
          id: e.id,
          x: e.x,
          y: e.y,
          width: e.width,
          height: e.height,
          rotation: e.rotation,
          label: e.label,
          capacity: e.capacity,
        });
        break;
      case 'stage':
        out.stages.push({
          id: e.id,
          x: e.x,
          y: e.y,
          width: e.width,
          height: e.height,
          rotation: e.rotation,
          label: e.label,
        });
        break;
      case 'table':
        out.tables.push({
          id: e.id,
          x: e.x,
          y: e.y,
          width: e.width,
          height: e.height,
          rotation: e.rotation,

        });
        break;
      case 'wall':
        out.walls.push({
          id: e.id,
          x: e.x,
          y: e.y,
          width: e.width,
          height: e.height,
          rotation: e.rotation,
        });
        break;
      case 'seat':
        out.seats.push(editorSeatToPreviewApi(e));
        break;
      default:
        break;
    }
  }
  return out;
}

function normalizeHallElementsFromJson(raw: unknown): any[] {
  if (!Array.isArray(raw)) {
    return [];
  }
  const out: any[] = [];
  for (const item of raw) {
    if (!item || typeof item !== 'object') {
      continue;
    }
    const o = item as Record<string, unknown>;
    if (typeof o.id !== 'string' || typeof o.type !== 'string') {
      continue;
    }
    const typeRaw = o.type === 'stage_round' ? 'stage' : o.type;
    if (!['seat', 'table', 'stage', 'wall', 'sector', 'zone'].includes(typeRaw)) {
      continue;
    }
    const type = typeRaw as any['type'];
    const num = (v: unknown, fb: number) => {
      const n = typeof v === 'number' ? v : Number(v);
      return Number.isFinite(n) ? n : fb;
    };
    const isSeat = type === 'seat';
    const el: any = {
      id: o.id,
      type,
      x: num(o.x, 0),
      y: num(o.y, 0),
      width: isSeat ? 0 : num(o.width, 1),
      height: isSeat ? 0 : num(o.height, 1),
      rotation: num(o.rotation, 0),
      label: typeof o.label === 'string' ? o.label : '',
    };
    if (type === 'seat') {
      el.radius = num(o.radius, HALL_SEAT_SIZE / 2);
      const optStr = (v: unknown) => {
        if (v == null) {
          return undefined;
        }
        const s = String(v).trim();
        return s.length ? s : undefined;
      };
      const sn = optStr(o.seatNumber);
      if (sn !== undefined) {
        el.seatNumber = sn;
      }
      const sr = optStr(o.seatRow);
      if (sr !== undefined) {
        el.seatRow = sr;
      }
      if (typeof o.beltId === 'string' && o.beltId.length > 0) {
        el.beltId = o.beltId;
      }
      const sid = optStr(o.sectorId);
      if (sid !== undefined) {
        el.sectorId = sid;
      }
      const sname = optStr(o.sectorName);
      if (sname !== undefined) {
        el.sectorName = sname;
      }
    } else if (type === 'zone') {
      const c = o.capacity;
      const cap = typeof c === 'number' && Number.isFinite(c)
        ? Math.floor(c)
        : (typeof c === 'string' && c.trim() ? Math.floor(Number(c)) : 0);
      el.capacity = Number.isFinite(cap) ? Math.max(0, cap) : 0;
    }
    out.push(el);
  }
  return out;
}

function previewSeatRadius(s: HallSeatType): number {
  const r = s.radius;
  if (typeof r === 'number' && Number.isFinite(r) && r > 0) {
    return r;
  }
  return HALL_SEAT_SIZE / 2;
}

type DialogHallPreviewProps = {
  hall: HallType | null;
  width: number;
  height: number;
};

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

  const geometry = useMemo((): PreviewHallGeometry | null => {
    if (!hall) {
      return null;
    }
    if (hallGeometryItemCount(hall) > 0) {
      return {
        sectors: hall.sectors ?? [],
        zones: hall.zones ?? [],
        stages: hall.stages ?? [],
        tables: hall.tables ?? [],
        walls: hall.walls ?? [],
        seats: hall.seats ?? [],
      };
    }
    const withLegacy = hall as HallType & { elements?: unknown };
    if (Array.isArray(withLegacy.elements) && withLegacy.elements.length > 0) {
      return legacyElementsToPreviewGeometry(normalizeHallElementsFromJson(withLegacy.elements));
    }
    return {
      sectors: [],
      zones: [],
      stages: [],
      tables: [],
      walls: [],
      seats: [],
    };
  }, [hall]);

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

  const stageCssW = HALL_STAGE_SIZE * scale;
  const stageCssH = HALL_STAGE_SIZE * scale;
  const offsetX = (width - stageCssW) / 2;
  const offsetY = (height - stageCssH) / 2;

  const belts = hall?.belts;

  return (
    <div
      className="relative overflow-hidden rounded-md bg-white outline-1 outline-slate-300"
      style={{ width, height }}
    >
      <div
        className="absolute"
        style={{
          left: offsetX,
          top: offsetY,
          width: stageCssW,
          height: stageCssH,
        }}
      >
        <Stage
          width={HALL_STAGE_SIZE}
          height={HALL_STAGE_SIZE}
          scaleX={scale}
          scaleY={scale}
          listening={false}
        >
          <Layer listening={false}>
            {geometry && (geometry.sectors ?? []).map((item) => (
              <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={item.x}
                  y={item.y - 22}
                  width={item.width}
                  align="center"
                  text={item.label ?? ''}
                  fontSize={14}
                  fill={HALL_SECTOR.labelRegular}
                  listening={false}
                />
              </React.Fragment>
            ))}
            {geometry && (geometry.zones ?? []).map((item) => (
              <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={item.x}
                  y={item.y + item.height / 2 - 8}
                  width={item.width}
                  align="center"
                  text={item.label ?? ''}
                  fontSize={16}
                  fill={HALL_SECTOR.labelNoSeats}
                  listening={false}
                />
                <Text
                  x={item.x}
                  y={item.y + item.height / 2 + 12}
                  width={item.width}
                  align="center"
                  text={`Вместимость: ${Math.max(0, Math.floor(Number(item.capacity ?? 0) || 0))} человек`}
                  fontSize={12}
                  fill={HALL_SECTOR.capacityText}
                  listening={false}
                />
              </React.Fragment>
            ))}
          </Layer>

          <Layer listening={false}>
            {geometry && (geometry.stages ?? []).map((item) => (
              <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) => (
              <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) => (
              <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) => {
              const seatLabel = formatHallSeatRowSlashNumber(item.seatRow, item.seatNumber);
              const seatR = previewSeatRadius(item);
              return (
                <React.Fragment key={item.id}>
                  <Circle
                    x={item.x}
                    y={item.y}
                    radius={seatR}
                    fill={resolveHallSeatApiFill(item, belts)}
                    listening={false}
                  />
                  <Text
                    x={item.x - seatR}
                    y={item.y - seatR}
                    width={2 * seatR}
                    height={2 * seatR}
                    align="center"
                    verticalAlign="middle"
                    wrap="none"
                    text={seatLabel}
                    fontSize={hallSeatLabelFontSizeForRect(
                      seatLabel,
                      2 * seatR,
                      2 * seatR,
                    )}
                    fontStyle="bold"
                    fontFamily="Arial,sans-serif"
                    fill={hallSeatApiLabelFill(item, belts)}
                    listening={false}
                  />
                </React.Fragment>
              );
            })}
          </Layer>
        </Stage>
      </div>
    </div>
  );
};

export default DialogHallPreview;
