/**
 * WorkspaceCanvas — die zoom-/verschiebbare "Landkarte" plus Fokus-Modus.
 *
 * Zwei Ebenen uebereinander:
 *  1. Welt-Ebene (skaliert/verschoben): nur leichte Thumbnail-Kacheln. Hier
 *     wirken 2-Finger-Pinch-Zoom + 2-Finger-Pan (nur in der Uebersicht).
 *  2. Identity-Content-Ebene (Scale 1, nie transformiert): die schweren,
 *     interaktiven Inhalte (ChatScreen + WebViews). Alle sichtbaren Kacheln
 *     sind hier IMMER gemountet; nur die fokussierte ist per display sichtbar.
 *     Dadurch bleiben Touch-Koordinaten/Keyboard korrekt und nichts remountet
 *     beim Fokuswechsel.
 *
 * Tap auf eine Thumbnail-Kachel → Fokus (voll aufgezoomt + interaktiv). Der
 * "⤢ Übersicht"-Button bzw. der Hardware-Back fuehren zurueck zur Landkarte.
 * Bei nur einer Kachel (reiner Chat) ist diese dauerhaft fokussiert und der
 * Canvas verhaelt sich exakt wie der bisherige Vollbild-Chat.
 */

import React, { useEffect, useMemo, useState } from 'react';
import { BackHandler, StyleSheet, Text, useWindowDimensions, View } from 'react-native';
import Animated, { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
import { Gesture, GestureDetector } from 'react-native-gesture-handler';

import {
  boundsOf, Camera, focusCamera, overviewCamera, TileId, TILE_RECTS, toLocal,
} from './layout';
import cockpitNav from '../services/cockpitNav';
import Tile from './Tile';
import { useWorkspaceLayout } from './useWorkspaceLayout';
import ChatTile from './tiles/ChatTile';
import CodeEditorTile from './tiles/CodeEditorTile';
import VncTile from './tiles/VncTile';
import PreviewTile from './tiles/PreviewTile';

interface Props {
  projectId: string;
  visibleTiles: TileId[];
  subtitles?: Partial<Record<TileId, string>>;
}

const ANIM = { duration: 260 };
const MIN_SCALE = 0.15;
const MAX_SCALE = 4;

const WorkspaceCanvas: React.FC<Props> = ({ projectId, visibleTiles, subtitles }) => {
  const { width: vw, height: vh } = useWindowDimensions();
  const [focusedTileId, setFocusedTileId] = useState<TileId | null>('chat');

  const visibleKey = visibleTiles.join(',');
  const bounds = useMemo(() => boundsOf(visibleTiles), [visibleKey]);
  const worldW = bounds.w;
  const worldH = bounds.h;
  const { loaded: layoutLoaded, getFocus, saveFocus } = useWorkspaceLayout(projectId);

  // Kamera (shared values fuer 60fps auf dem UI-Thread).
  const scale = useSharedValue(1);
  const tx = useSharedValue(0);
  const ty = useSharedValue(0);
  const savedScale = useSharedValue(1);
  const savedTx = useSharedValue(0);
  const savedTy = useSharedValue(0);

  // Verschwindet die fokussierte Kachel aus der Sichtbarkeit → auf Chat zurueck.
  useEffect(() => {
    if (focusedTileId && !visibleTiles.includes(focusedTileId)) {
      setFocusedTileId('chat');
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [visibleKey]);

  // Zuletzt fokussierte Kachel pro Projekt wiederherstellen.
  useEffect(() => {
    if (!layoutLoaded) return;
    const stored = getFocus();
    if (stored === undefined) return;
    if (stored === null || visibleTiles.includes(stored)) setFocusedTileId(stored);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [projectId, layoutLoaded, visibleKey]);

  // Fokus-Wahl persistieren.
  useEffect(() => {
    if (layoutLoaded) saveFocus(focusedTileId);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [focusedTileId, layoutLoaded]);

  // Kamera auf das Ziel fahren (Fokus-Rect oder Uebersicht).
  useEffect(() => {
    const cam: Camera = focusedTileId
      ? focusCamera(toLocal(TILE_RECTS[focusedTileId], bounds), worldW, worldH, vw, vh)
      : overviewCamera(worldW, worldH, vw, vh);
    scale.value = withTiming(cam.scale, ANIM);
    tx.value = withTiming(cam.tx, ANIM);
    ty.value = withTiming(cam.ty, ANIM);
    savedScale.value = cam.scale;
    savedTx.value = cam.tx;
    savedTy.value = cam.ty;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [focusedTileId, visibleKey, vw, vh]);

  // Fokus-Zustand + „zur Uebersicht"-Aktion an den Header (cockpitNav) melden,
  // damit der Uebersicht-Button dort sitzt (kollidiert nicht mit dem Chat).
  useEffect(() => {
    cockpitNav.setFocused(focusedTileId != null);
    cockpitNav.registerOverview(() => setFocusedTileId(null));
    return () => { cockpitNav.registerOverview(null); cockpitNav.setFocused(false); };
  }, [focusedTileId]);

  // Hardware-Back: im Fokus → zurueck zur Uebersicht.
  useEffect(() => {
    const onBack = () => {
      if (focusedTileId) {
        setFocusedTileId(null);
        return true;
      }
      return false;
    };
    const sub = BackHandler.addEventListener('hardwareBackPress', onBack);
    return () => sub.remove();
  }, [focusedTileId]);

  // Gesten nur in der Uebersicht (Fokus-Modus: Touches fallen an die Kachel).
  const gesturesEnabled = !focusedTileId;
  const canvasGesture = useMemo(() => {
    const pinch = Gesture.Pinch()
      .enabled(gesturesEnabled)
      .onUpdate((e) => {
        'worklet';
        scale.value = Math.max(MIN_SCALE, Math.min(MAX_SCALE, savedScale.value * e.scale));
      })
      .onEnd(() => {
        'worklet';
        savedScale.value = scale.value;
      });
    const pan = Gesture.Pan()
      .enabled(gesturesEnabled)
      .minPointers(2)
      .onUpdate((e) => {
        'worklet';
        tx.value = savedTx.value + e.translationX;
        ty.value = savedTy.value + e.translationY;
      })
      .onEnd(() => {
        'worklet';
        savedTx.value = tx.value;
        savedTy.value = ty.value;
      });
    return Gesture.Simultaneous(pinch, pan);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [gesturesEnabled]);

  const worldStyle = useAnimatedStyle(() => ({
    transform: [
      { translateX: tx.value },
      { translateY: ty.value },
      { scale: scale.value },
    ],
  }));

  const renderContent = (id: TileId) => {
    switch (id) {
      case 'chat': return <ChatTile />;
      case 'editor': return <CodeEditorTile projectId={projectId} />;
      case 'vnc': return <VncTile projectId={projectId} focused={focusedTileId === 'vnc'} />;
      case 'preview': return <PreviewTile />;
      default: return null;
    }
  };

  return (
    <View style={styles.root}>
      {/* Ebene 1 — skalierte Landkarte mit Thumbnails */}
      <View style={StyleSheet.absoluteFill} pointerEvents={focusedTileId ? 'none' : 'auto'}>
        <GestureDetector gesture={canvasGesture}>
          <Animated.View style={[styles.world, { width: worldW, height: worldH }, worldStyle]}>
            {visibleTiles.map((id) => (
              <Tile
                key={id}
                id={id}
                rect={toLocal(TILE_RECTS[id], bounds)}
                subtitle={subtitles?.[id]}
                onFocus={setFocusedTileId}
              />
            ))}
          </Animated.View>
        </GestureDetector>
      </View>

      {/* Ebene 2 — Identity-Content, immer gemountet, nur fokussierte sichtbar */}
      <View style={StyleSheet.absoluteFill} pointerEvents={focusedTileId ? 'box-none' : 'none'}>
        {visibleTiles.map((id) => (
          <View
            key={id}
            style={[StyleSheet.absoluteFill, { display: focusedTileId === id ? 'flex' : 'none' }]}
          >
            {renderContent(id)}
          </View>
        ))}
      </View>

      {/* Steuerung — der „⤢ Übersicht"-Button sitzt im Header (cockpitNav),
          nicht hier im Chat-Inhalt. */}
      {!focusedTileId && (
        <View style={styles.hintBar} pointerEvents="none">
          <Text style={styles.hintText}>Kachel antippen zum Öffnen · 2 Finger: zoomen & schieben</Text>
        </View>
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  root: { flex: 1, backgroundColor: '#0D0D1A' },
  world: { position: 'absolute', left: 0, top: 0 },
  hintBar: {
    position: 'absolute',
    bottom: 16,
    left: 0,
    right: 0,
    alignItems: 'center',
  },
  hintText: {
    color: '#9090B0',
    fontSize: 12,
    backgroundColor: 'rgba(18,18,42,0.85)',
    paddingHorizontal: 12,
    paddingVertical: 6,
    borderRadius: 14,
    overflow: 'hidden',
  },
});

export default WorkspaceCanvas;
