import React, { useMemo } from 'react';

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

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

import {
  formatHallSeatRowSlashNumber,
  hallSeatApiLabelFill,
  hallSeatLabelFontSizeForRect,
  getHallBlockCornerRadius,
  getHallBlockOnShapeTextFill,
  HALL_ELEMENT_DEFAULTS,
  HALL_SEAT_SIZE,
  HALL_SECTOR,
  HALL_STAGE_SIZE,
  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: HallElementType): 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: HallElementType[]): 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,
          label: e.label,
        });
        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): HallElementType[] {
  if (!Array.isArray(raw)) {
    return [];
  }
  const out: HallElementType[] = [];
  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 HallElementType['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: HallElementType = {
      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}
                                />
                                <Text
                                    x={item.x + 6}
                                    y={item.y + 6}
                                    text={item.label ?? ''}
                                    fontSize={12}
                                    fill={getHallBlockOnShapeTextFill('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;
